Mule ESB + RabbitMQ reliability and up-time: how to re-create a deleted exchange automatically at runtime - queue

I've got a Large mule application that receives on multiple queues and publishes to at least one exchange. I'm manually QA'ing the application by deleting the queues and exchanges to see if mule will retry to connect (and also shut down rabbit altogether)
This question is for when an exchange is deleted. The messages go into a locked anonymous queue named something like: amq.gen-gFs6-7sP2nw1ntgobO6cBg
I'm looking for a way to reconnect the exchange and still pass through the messages. Is this even possible?
I've set options like
exchangeDurable="true"
queueDurable="true"
Is there any other things (or rabbit configs) that I need to do or would be beneficial to me?
Next Test: Shutdown RabbitMQ in the middle of processing.
Code:
<mule xmlns:jdbc-ee="http://www.mulesoft.org/schema/mule/ee/jdbc"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:amqp="http://www.mulesoft.org/schema/mule/amqp"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.4.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
xmlns:file="http://www.mulesoft.org/schema/mule/file"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/ee/jdbc http://www.mulesoft.org/schema/mule/ee/jdbc/current/mule-jdbc-ee.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/amqp http://www.mulesoft.org/schema/mule/amqp/current/mule-amqp.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd"
xmlns:context="http://www.springframework.org/schema/context">
<amqp:connector name="amqpAutoAckLocalhostConnector"
host="${config.status_reporting.host}"
port="${config.status_reporting.port}"
virtualHost="${config.status_reporting.virtual_host}"
username="${config.status_reporting.username}"
password="${config.status_reporting.password}"
requestedHeartbeat="${config.status_reporting.requestedHeartbeat}"
doc:name="AMQP Connector for Status Messages"/>
<flow name="send_status" doc:name="send_status">
<vm:inbound-endpoint path="send_status" exchange-pattern="one-way" responseTimeout="10000" doc:name="VM" />
<logger message="starting send status" level="DEBUG" doc:name="Logger"/>
<!-- some code here has been removed for stackoverflow question -->
<flow-ref name="cwm_send" doc:name="flow ref"/>
</flow>
<flow name="cwm_send" doc:name="cwm_send">
<amqp:outbound-endpoint exchangeName="${config.status_reporting.exchange_name}"
exchangeType="topic"
exchangeDurable="${config.status_reporting.exchange_is_durable}"
routingKey="${config.status_reporting.routing_key}"
connector-ref="amqpAutoAckLocalhostConnector" doc:name="AMQP Out" queueDurable="true" responseTimeout="10000"/>
</flow>
<flow name="send_ingest_status" doc:name="send_ingest_status">
<vm:inbound-endpoint exchange-pattern="request-response" responseTimeout="10000" doc:name="VM" path="send_ingest_status"/>
<vm:outbound-endpoint path="send_status" exchange-pattern="one-way" doc:name="Send Status">
<set-payload value="#[[
'status_code': 'foo',
'status_descr': 'test description.',
'status_final': '0',
'version': '1.0']]"/>
</vm:outbound-endpoint>
</flow>
</mule>
Thank you.

This problem also seems to occur when an exchange is declared only in an outbound endpoint. There is an open bug concerning this in the Mulesoft JIRA, and you can vote for it to help them prioritize it.
I took a look at the source code, and the problem seems to be that there is simply no code to declare exchanges when an outbound endpoint is started. In your case, you'd probably want the code to run at the time the message is sent, or maybe at the time the exchange is deleted. This timing wouldn't be covered by the aforementioned bug, but you might open a new issue describing the use case and the desired functionality. And a pull request would probably be even better! ;)

Related

Mule: how to consume a service from a remote client

I have been following this tutorial which is really great to consume wb services from WSDL http://training.middlewareschool.com/mule/consuming-wsdl-first-service/.
I have been trying to do a similar approach by generating a client web service in Eclipse using CXF and publishing the web service in Mule. My question is: if I configure for the client and mule application to have the same endpoint (for example: localhost:8082/ipsoap/test), how can I have the web service work the same way as with the tutorial.
Meaning if I test sending a request to mule from the client (in eclipse) I should receive the right response from mule. Thank you in advance for your time.
So in short:
1-I generated a client app in eclipse using the wsdl in the following link in the tutorial: http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl
2- As a start in Mule, I added an http connector and a logger and changed the endpoint path in eclipse to the one I set on the HTTP connector on Mule. Thus, I can see that there is a payload when I am sending a request to Mule from the client in Eclipse.
3- I need to have an application, namely my client app in eclipse, consume a published service in Mule. Now I think this is achieved using the CXF component but I still fail to make it work. In fact, I wonder if this is one valid way of using Mule since I couldn't find any tutorial about what I am trying to achieve.
So here is how I test it:
I used the same endpoint I used in Mule and receive the following log:
> INFO 2014-07-07 13:19:46,124
> [[soapservice].connector.http.mule.default.receiver.02]
> org.mule.api.processor.LoggerMessageProcessor: message transformation
> <soapenv:Envelope
> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
> xmlns:q0="http://ws.cdyne.com/"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> <soapenv:Body>
> <q0:ResolveIP>
> <q0:ipAddress>173.194.36.39</q0:ipAddress>
> <q0:licenseKey/>
> </q0:ResolveIP> </soapenv:Body> </soapenv:Envelope>
>
> ERROR 2014-07-07 13:19:46,134
> [[soapservice].connector.http.mule.default.receiver.02]
> org.mule.exception.DefaultMessagingExceptionStrategy:
> ******************************************************************************** Message : wrong number of arguments. Failed to route
> event via endpoint: org.mule.module.cxf.CxfOutboundMessageProcessor.
> Message payload is of type: String Code :
> MULE_ERROR--2
> -------------------------------------------------------------------------------- Exception stack is:
> 1. wrong number of arguments (java.lang.IllegalArgumentException) sun.reflect.NativeMethodAccessorImpl:-2 (null)
> 2. wrong number of arguments. Failed to route event via endpoint: org.mule.module.cxf.CxfOutboundMessageProcessor. Message payload is of
> type: String (org.mule.api.transport.DispatchException)
> org.mule.module.cxf.CxfOutboundMessageProcessor:150
> (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transport/DispatchException.html)
> -------------------------------------------------------------------------------- Root Exception stack trace: java.lang.IllegalArgumentException: wrong
> number of arguments at
> sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
> sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
> + 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
As you can see the soap request can be seen but it is not consumed at the level of the CXF component. Here is my mule code:
<flow name="SoapService" doc:name="SoapService">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="test/cap.asmx" doc:name="HTTP"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<logger message="message transformation #[message.payload]" level="INFO" doc:name="Logger"/>
<flow-ref name="RequestResponse" doc:name="Flow Reference"/>
<logger level="INFO" doc:name="Logger" message="after posting #[message.payload]"/>
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
</flow>
<flow name="RequestResponse" doc:name="RequestResponse">
<cxf:jaxws-client operation="ResolveIP" clientClass="pck.IP2Geo" port="IP2GeoSoap" wsdlLocation="file:/C:/Users/12204-hajjam1/workspace/ipgo/src/ipgeo.wsdl" doc:name="soap 2"/>
<logger message="before posting #[message.payload]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:10387/ip2geo/ip2geo.asmx" doc:name="HTTP"/>
</flow>
Also if I add a set payload with the ip #[{'173.194.36.39',''}] (the second argument can be left empty) before the cxf component it returns a an empty element. Yet, the response should be something like this:
<pck.IPInformation>
<city>Mountain View</city>
<stateProvince>CA</stateProvince>
<country>United States</country>
<organization/>
<latitude>37.4192</latitude>
<longitude>-122.0574</longitude>
<areaCode>0</areaCode>
<timeZone/>
<hasDaylightSavings>false</hasDaylightSavings>
<certainty>90</certainty>
<regionName/>
<countryCode>US</countryCode>
</pck.IPInformation>
Thus, my problem is with the consumption and retrieval of the response.
I apologize for the length but I have been struggling with this and haven't found a solution online. Thanks in advance.
You should create an instance of the message class that as been generated for the ResolveIP method from the WSDL and use it as the message payload before the cxf:jaxws-client element.

Mule ESB 3.4.0CE Sending message to multiple outbound endpoints that are added/removed dynamically

I am working on a part of a Mule ESB application and the issue I am having is very analogous to a chat room.
The chat room (server, Mule ESB) can listen for many chatters (clients, external applications) and when a single chatter (c1) inputs a message, the server echos it to all the other chatters, except for c1. In my case though, I would need to also echo it to c1.
I am having a hard time wrapping my mind around some detailed aspects of how the message processing works in Mule ESB. I read the documentation about transports and believe I may need to work with Message Receivers and Message Dispatchers.
Consider the following configuration:
<mule ...>
<tcp:connector name="tcpConn" doc:name="TCP connector" clientSoTimeout="0" keepAlive="true" keepSendSocketOpen="true" receiveBacklog="0" receiveBufferSize="0" reuseAddress="true" sendBufferSize="0" serverSoTimeout="0" socketSoLinger="0" validateConnections="true">
<reconnect-forever />
<tcp:direct-protocol payloadOnly="true"/>
</tcp:connector>
</spring:beans>
<tcp:endpoint exchange-pattern="request-response" host="localhost" port="8090" name="ListenEndpoint" responseTimeout="10000" doc:name="TCP"/>
<flow name="ChatroomExampleFlow1" doc:name="ChatroomExampleFlow1">
<tcp:inbound-endpoint exchange-pattern="request-response" ref="ListenEndpoint" responseTimeout="10000" doc:name="Client Message"/>
<logger level="INFO" doc:name="Logger"/>
<all doc:name="All">
<tcp:outbound-endpoint host="${client1.host}" port="${client1.port}" responseTimeout="10000" doc:name="TCP"/>
<tcp:outbound-endpoint host="${client2.host}" port="${client2.port}" responseTimeout="10000" doc:name="TCP"/>
<tcp:outbound-endpoint host="${client3.host}" port="${client3.port}" responseTimeout="10000" doc:name="TCP"/>
</all>
</flow>
</mule>
If I know at configuration time the host and port of all clients, then this configuration holds. However, my goal is to be able to send out the messages to clients that have established a connection, which could be up to n clients. As more clients connect/disconnect, I would need to add or remove them from the list.
There exists a <recipient-list expression="#[app.registry.remoteEndpoints]"/> where the expression should evaluate to a List of endpoints and the flow will send the message to every endpoint in the collection. However, for my purposes this does not work (see answer below). See the documentation for recipient list
<mule ...>
<tcp:connector name="tcpConn" doc:name="TCP connector" clientSoTimeout="0" keepAlive="true" keepSendSocketOpen="true" receiveBacklog="0" receiveBufferSize="0" reuseAddress="true" sendBufferSize="0" serverSoTimeout="0" socketSoLinger="0" validateConnections="true">
<reconnect-forever />
<tcp:direct-protocol payloadOnly="true"/>
</tcp:connector>
<spring:beans>
<spring:bean name="remoteEndpoints" scope="singleton" class="java.util.ArrayList"/>
</spring:beans>
<tcp:endpoint host="localhost" exchange-pattern="one-way" port="8090" name="ListenEndpoint" responseTimeout="10000" doc:name="TCP"/>
<flow name="ChatroomExampleFlow1" doc:name="ChatroomExampleFlow1">
<tcp:inbound-endpoint ref="ListenEndpoint" responseTimeout="10000" doc:name="Client Message"/>
<echo-component doc:name="Echo"/>
<component class="EndpointStorer" doc:name="Java"/>
<recipient-list expression="#[app.registry.remoteEndpoints]"/>
</flow>
</mule>
And with EndpointStorer looking like this:
public Object onCall(MuleEventContext eventContext) throws Exception
{
Registry registry = eventContext.getMuleContext().getRegistry();
MuleMessage message = eventContext.getMessage();
ArrayList arrList = (ArrayList) registry.get("remoteEndpoints");
Object remoteAddress = message.getOutboundProperty("MULE_REMOTE_CLIENT_ADDRESS");
String tcpAddr = "tcp://" + remoteAddress.toString().substring(1); //substring 1 because we see the remote client address as something like /127.0.0.1:4943
if (!arrList.contains(tcpAddr))
{
arrList.add(tcpAddr);
}
return message;
}
You can't reach established inbound TCP connections, at least not using TCP outbound endpoints. It may be possible to extend the TCP connector to expose the Socket in http://github.com/mulesoft/mule/blob/mule-3.x/transports/tcp/src/main/… but it's no small feat.
You could consider using the AJAX transport.

How to forward SOAP request through ACTIVE MQ JMS to my Services with the support of MULE

We have produced JAX-WS web-services with the help of Java API and published. Now we would like to queuing the requests, which are coming for the services with the help of JMS. We chosen the ACTIVE MQ JMS Server with the combination of MULE ESB.
We have tried the proxying of webservices with the help of two Http Endpoints. It is working fine. So When i trying to test it by sending request from SOAP UI to Http inbound end point, it is forwarding request to my services and get back the response to SOAP UI.
But when we are trying to put the JMS endpoint in between these Http end points, the request is forwarded to my services, but not the message (SOAP).
Please help me to resolve the issue or suggest me the alternative way for Queuing.
Following image shows flow in MULE.
.
Following is the flow :
<jms:activemq-connector name="Active_MQ1" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
<flow name="finalFlow1" doc:name="finalFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8888" contentType="text/xml" doc:name="HTTP"/>
<jms:outbound-endpoint exchange-pattern="request-response" queue="servicesQueue" connector-ref="Active_MQ1" doc:name="JMS"/>
<http:outbound-endpoint mimeType="text/xml" doc:name="HTTP" exchange-pattern="request-response" method="POST" path="MyServices" host="localhost" port="5050" />
</flow>
Actually MyServices is produced at http://localhost:5050/MyServices
The problem is probably due to that you are expecting a string payload in your JMS queue and the http:inbound-endpoint produces a stream payload.
Try putting <object-to-string-transformer/> before the jms:outbound-endpoint.

Mule ESB How to dump POST payload to a file

I am getting started with Mule ESB. I am trying to build a SOAP proxy service that receives a SOAP request and redirects it to a SOAP service.
A simple example like this works fine -
<flow name="http_redirectFlow1" doc:name="http_redirectFlow1">
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8092/HelloProxyService" doc:name="HTTP"/>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:8080/soapsvc/hello" contentType="text/xml" doc:name="HTTP"/>
</flow>
Now I want to dump the contents of the request to a file. Which is the best way to do it? I tried to use the File connector by inserting this segment between the inbound and outbound endpoints -
<file:outbound-endpoint path="c:/temp" outputPattern="temp.txt" responseTimeout="10000" doc:name="File"/>
But that doesn't seem to work. I get an exception that says "Content must be set before entity is written". Not sure what it is, but I may be completely wrong in how I am doing. Please help....
Figured it out myself. I had to translate the DOM to XML using the dom-to-xml transformer. The XML dump is done as follows :-
<mulexml:dom-to-xml-transformer returnClass="java.lang.String"></mulexml:dom-to-xml-transformer>
<file:outbound-endpoint path="c:/temp" outputPattern="Dump_Rcvd.txt" responseTimeout="10000" doc:name="File" />
Thanks !
Alternately you can use <object-to-string-transformer doc:name="Object to String"/> before file:outbound-endpoint that will make the payload as a String format and can be written into a file easily
Use File Connector and Transformers involving Bytearray.

How to transform javax.mail.internet.MimeMessage to java.io.InputStream in Mule

I tried to read a file and email through Mule. But it throws the following exception.
org.mule.api.transformer.TransformerException: Could not find a transformer to transform "SimpleDataType{type=javax.mail.internet.MimeMessage, mimeType='*/*'}" to "SimpleDataType{type=java.io.InputStream, mimeType='*/*'}".
at org.mule.registry.MuleRegistryHelper.lookupTransformer(MuleRegistryHelper.java:252)
at org.mule.DefaultMuleMessage.getPayload(DefaultMuleMessage.java:355)
at org.mule.DefaultMuleMessage.getPayload(DefaultMuleMessage.java:313)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
My mule file is as follows:
<flow name="Exception_HandlingFlow1" doc:name="Exception_HandlingFlow1">
<file:inbound-endpoint path="D:\WorkArea\COPA\In" responseTimeout="10000" doc:name="File Writer">
<file:file-to-string-transformer/>
</file:inbound-endpoint>
<component doc:name="Java" class="com.exhnlr.Handler.ExceptionHandler"/>
<smtps:outbound-endpoint host="192.168.131.139" responseTimeout="10000" doc:name="SMTP"
from="anbu1#bibs.com" subject="test" to="anbu1#bibs.com" user="anbu1" mimeType="text/plain">
<email:string-to-email-transformer/>
</smtps:outbound-endpoint>
</flow>
I have read a similiar link How to parse inbound e-mail when using Mule's IMAP transport?, but it didn't work for me.
Please help.
Add an <object-to-string-transformer /> after the file inbound endpoint.