Mule Amqp plugin and Mel - rabbitmq

I want to post message to exchange with routing key. The message witch I want to send is from payload, but routing key I'm seting in message in inbound properties, and then I set:
routingKey="#[message.inboundProperties.routingKey]" but it not working
<flow name="ExportToFk" doc:name="ExportToFk">
<vm:inbound-endpoint exchange-pattern="one-way" path="rabbitSenderVM" doc:name="SendToRabbit"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[import org.mule.api.transport.PropertyScope
def xml = payload.xml
def routingKey = payload.routing
println "XML: $xml"
println "ROUTINGKEY: $routingKey"
message.setProperty('routingKey', routingKey, PropertyScope.INBOUND)
return xml]]></scripting:script>
</scripting:component>
<amqp:outbound-endpoint exchangeName="${amqp.exchange}" routingKey="#[message.inboundProperties.routingKey]" responseTimeout="10000" connector-ref="AMQP_Connector" doc:name="AMQP"/>
</flow>

This is a known issue, which is currently under development: https://github.com/mulesoft/mule-transport-amqp/issues/24

Related

How to configure mule requester?

I get messages from one jms queue. I'm using mule requester component but how can i give that jms queue path in resources option ?
Please assist me., Thanks.,
Pass in the queue in URL format:
<mulerequester:request config-ref="Mule_Requester" resource="jms://input?connector=AMQConnector1" doc:name="Request a message from a queue" />
The Mule config will be :
-<mulerequester:config name="Mule_Requester" doc:name="Mule Requester"/> <jms:activemq-connector name="Active_MQ" brokerURL="tcp://localhost:61616" specification="1.1" doc:name="Active MQ"/> <flow name="QueueRequester" doc:name="QueueRequester"> <http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="fetch" doc:name="HTTP"/> <mulerequester:request config-ref="Mule_Requester" resource="jms://input" doc:name="Request a message from a queue" /> <logger message="Payload from JMS message: #[payload]" level="WARN" doc:name="Logger"/> </flow>
Now suppose there is a JMS queue named input from where we need to fetch data in our flow on we hit the url : `http://localhost:8081/fetch '.

How to use Mule Expression in JMS:selector

I checked several previous discussions but couldnt find the answer.
I am trying to achieve synchronous communicaiton using JMS back-channel (http://www.whishworks.com/blog/synchronous-communication-using-jms-back-channel). Apart from the things mentioned in that site, I need to filter out the message from the inbound queue based on a dynamic Id.
Following are my mule flows:
<flow name="serverFlow" >
<jms:inbound-endpoint doc:name="REQUEST" queue="REQUEST.QUEUE" connector-ref="jmsConnector">
<jms:selector expression="MULE_CORRELATION_ID='#[sessionVars.myCorrelationId]'"/>
</jms:inbound-endpoint>
<set-payload value="#[payload] + Hello World from Receiver" doc:name="Set Payload" />
<jms:outbound-endpoint doc:name="REPLY" queue="REPLY.QUEUE" connector-ref="jmsConnector" />
</flow>
<flow name="mainFlow" >
<http:listener config-ref="HTTP_Listener_Configuration" path="/jms" allowedMethods="GET" doc:name="HTTP"/>
<set-session-variable variableName="myCorrelationId" value="#[System.currentTimeMillis().toString()]" doc:name="Set Correlation ID"/>
<set-payload value="New message sent from Mule - mainFlow at #[new Date()]" doc:name="Set Message"/>
<set-property propertyName="MULE_CORRELATION_ID" value="#[sessionVars.myCorrelationId]" doc:name="Property"/>
<request-reply doc:name="Request-Reply">
<jms:outbound-endpoint doc:name="REQUEST" connector-ref="jmsConnector" queue="REQUEST.QUEUE"/>
<jms:inbound-endpoint doc:name="REPLY" connector-ref="jmsConnector" queue="REPLY.QUEUE"/>
</request-reply>
<logger message="Reply to sender: #[message]" level="WARN" doc:name="Logger" />
</flow>
If I try a static value like "<jms:selector expression="MULE_CORRELATION_ID='12345'"/>", it works. But if I try a dynamic ID using MEL, its not working. The MEL inside the jms selector expression is not working. The message stays at the queue as Unread. I used logs to see what the MULE_CORRELATION_ID is while being set at mainFlow and found the same value is set in the message that is UNREAD in the queue. So, I guess nothing is wrong in the way the MULE_CORRELATION_ID is set. The only problem is that MEL is not working within jms:selector.
Could you please help how to get MEL working within JMS selector?
Thank you very much.
MEL is working fine in the selector but its usage is very limited. When the JMS selector is created, there's no in-flight event available to Mule so none of the event-bound data (including session) is available.
To select a very particular message, you need to use a JMS message requester, constructed with the desired selector, like:
jms://REQUEST.QUEUE?selector=MULE_CORRELATION_ID%3D'#[sessionVars.myCorrelationId]'
Here is the working solution based on David's suggestion. I am using wmq here (not jms).
<mulerequester:config name="Mule_Requester" doc:name="Mule Requester"/>
<flow name="mainFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" allowedMethods="GET" doc:name="HTTP"/>
<set-payload value="My Message" doc:name="Set Message"/>
<set-property propertyName="JMSCorrelationID" value="12345" doc:name="Property"/>
<set-session-variable variableName="myCorrelationId" value="ID:313233343500000000000000000000000000000000000000" doc:name="Set Correlation ID"/>
<!--313233343500000000000000000000000000000000000000 is the MQMD CorrelationId for 12345. This is set by IBM MQ -->
<logger message="The Message to REQUEST QUEUE: #[message]" level="WARN" doc:name="Logger"/>
<wmq:outbound-endpoint queue="REQUEST.QUEUE" connector-ref="wmqConnector" doc:name="OUT"/>
<mulerequester:request config-ref="Mule_Requester" resource="wmq://REPLY.QUEUE?selector=JMSCorrelationID%3D'#[sessionVars.myCorrelationId]'" doc:name="Mule Requester" timeout="120000"/>
<logger message="Final Response: #[message]" level="WARN" doc:name="Logger"/>
</flow>
Please note, I manually moved the message from Request queue to Reply queue using MQVE for my testing. In real time, it will be done by another program.

JAXB with HTTP inbounds throws exception An invalid return type "class [B" was specified for transformer "JAXBMarshallerTransformer"

When I have XML payload from JMS inbound, XML to JAXB works as expected. But when I have same XML payload from HTTP inbound it throws an exception
An invalid return type "class [B" was specified for transformer "JAXBMarshallerTransformer" (org.mule.api.transformer.TransformerException)
Is it not a fair expectation from "XML to JAXB" component to have a XML payload from HTTP inbound? Please let me know what I am missing here.
Flow xml with with JMS and HTTP inbound. Only JMS inbound works as expected,
<flow name="productdemoFlow">
<jms:inbound-endpoint queue="my.test" connector-ref="Active_MQ" doc:name="JMS">
<jms:transaction action="NOT_SUPPORTED"/>
</jms:inbound-endpoint>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<mulexml:jaxb-xml-to-object-transformer returnClass="com.chc.model.Product" jaxbContext-ref="JAXB_Context" doc:name="XML to JAXB Object"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
<flow name="productdemoFlow1">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" allowedMethods="POST" doc:name="HTTP" />
<logger message="#["Payload ---------->" + payload.getClass().getName()]" level="INFO" doc:name="Logger"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<logger message="#["Payload ---------->" + payload]" level="INFO" doc:name="Logger"/>
<mulexml:jaxb-xml-to-object-transformer encoding="windows-1252" mimeType="application/xml" jaxbContext-ref="JAXB_Context" doc:name="XML to JAXB Object"/>
</flow>
If I am not wrong, what you see is what you would expect.
The JMS inbound endpoint follows (by default, as in your case) a "one way" pattern, there is no response message to the client so there is no special requirement for the payload at the end of the flow.
The HTTP inbound endpoint follows (by default, as in your case) a "request-response" pattern so the payload, before sending the response to the client, should be of a type managed by the endpoint. In your case it is a java object instance of a not managed type, it must be converted to a correct type (String, InputStream, byte[], ...). For example:
<mulexml:jaxb-object-to-xml-transformer />

Impossible to route: org.mule.transport.amqp.AmqpMessage

I'm having a random problem with amqp components in Mule.
This is the scenario:
I set a global AMQP connector to be used for both Mule Flows
<amqp:connector
name="amqpLocalhostConnector"
host="${amqp.host}"
port="${amqp.port}"
fallbackAddresses="${amqp.fallbackAddresses}"
virtualHost="${amqp.virtualHost}"
username="${amqp.username}"
password="${amqp.password}"
ackMode="MANUAL"
prefetchCount="1" />
This flows sends a notification to RabbitMQ
<flow
name="notifyRabbitMQ"
doc:name="notifyRabbitMQ">
<!-- Set the payload with an ID from an element in a database -->
<set-payload
doc:name="Set Payload"
value="123abc"/>
<!-- Send the ID into an amqp message to RabbitMQ -->
<amqp:outbound-endpoint
exchangeName="exchange"
routingKey="file.id"
connector-ref="amqpLocalhostConnector">
</amqp:outbound-endpoint>
</flow>
This flow gets the notification from the RabbitMQ queue and then process it.
<flow
name="processNotification"
doc:name="processNotification"
processingStrategy="synchronous">
<amqp:inbound-endpoint
queueName="files"
connector-ref="amqpLocalhostConnector" />
<byte-array-to-string-transformer doc:name="Message to String (ID)"/>
<set-payload
value="#[app.registry.customFileService.findFile(payload)]"
doc:name="Get File" />
<logger message="SUCCESS!" level="INFO" doc:name="Logger"/>
<amqp:acknowledge-message />
</flow>
When I run the project, sometimes it works fine and sometimes it throws the following error:
ERROR 2015-07-17 12:37:47,620 [[rabbit_notification].amqpLocalhostConnector.receiver.01] org.mule.transport.amqp.AmqpMessageReceiver$AmqpMessageRouterWork: Impossible to route: org.mule.transport.amqp.AmqpMessage#43cac8[consumerTag=amq.ctag-jASX98hPWb7UUiIVHLOeEQ,envelope=Envelope(deliveryTag=2, redeliver=false, exchange=exchange, routingKey=file.id),body={53,53,97,57,50,49,52,98,50,50,50,57,101,56,56,51,55,101,98,54,102,100,56,53},properties=#contentHeader(content-type=null, content-encoding=UTF-8, headers={MULE_SESSION=rO0ABXNyACNvcmcubXVsZS5zZXNzaW9uLkRlZmF1bHRNdWxlU2Vzc2lvbi7rdtEW7GGKAwAEWgAFdmFsaWRMAA1mbG93Q29uc3RydWN0dAAmTG9yZy9tdWxlL2FwaS9jb25zdHJ1Y3QvRmxvd0NvbnN0cnVjdDtMAAJpZHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wAD3NlY3VyaXR5Q29udGV4dHQAJ0xvcmcvbXVsZS9hcGkvc2VjdXJpdHkvU2VjdXJpdHlDb250ZXh0O3hwAXB0ACRjNjI4Zjc0Ny0yYzk5LTExZTUtYjI3YS1lMWM4ZmJjNTUzY2Fwc3IAJWphdmEudXRpbC5Db2xsZWN0aW9ucyRTeW5jaHJvbml6ZWRNYXAbc/kJS0s5ewMAAkwAAW10AA9MamF2YS91dGlsL01hcDtMAAVtdXRleHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwc3IAJG9yZy5tdWxlLnV0aWwuQ2FzZUluc2Vuc2l0aXZlSGFzaE1hcJ3R2e9nRc4AAwAAeHB3DD9AAAAAAAAQAAAAAHhxAH4ACXh4, MULE_ENCODING=UTF-8, MULE_ROOT_MESSAGE_ID=c628f745-2c99-11e5-b27a-e1c8fbc553ca, MULE_ENDPOINT=amqp://exchange}, delivery-mode=2, priority=0, correlation-id=null, reply-to=null, expiration=null, message-id=c628f745-2c99-11e5-b27a-e1c8fbc553ca, timestamp=Fri Jul 17 12:37:47 ART 2015, type=null, user-id=null, app-id=null, cluster-id=null)]
Does anyone knows why this could be happening?
Thanks in advance.

Get message inbound properties

im having trouble getting message inbound properties, somehow its coming as null, here is the code:
<scripting:transformer name="noopLoggingTransformer">
<scripting:script engine="groovy">
log.info "${message.getInboundProperty('user-agent')}"
muleContext.client.dispatch('vm://log-request.in', message)
message
</scripting:script>
</scripting:transformer>
<pattern:web-service-proxy name="service" transformer-refs="noopLoggingTransformer" inboundAddress="${serverName}/services/Logradouros/LogradouroServico" outboundAddress="${targetServer}/servicos/v2/service.svc" wsdlFile="LogradouroServicos.wsdl">
</pattern:web-service-proxy>
<jdbc-ee:postgresql-data-source name="WSA" user="${database.user}" password="${database.pass}" url="${database.url}" transactionIsolation="UNSPECIFIED" doc:name="PostgreSQL Data Source">
</jdbc-ee:postgresql-data-source>
<jdbc-ee:connector name="jdbcConnector" dataSource-ref="WSA" validateConnections="false" transactionPerMessage="true" queryTimeout="10" pollingFrequency="10000" doc:name="JDBC">
<jdbc-ee:query key="wsadb" value="insert into inbound_messages (payload, timestamp, agent, ip_from, endpoint, soap_operation) values ('', now(), #[groovy: return message.getInboundProperty('user-agent').toString()], #[groovy: return message.getInboundProperty('MULE_REMOTE_CLIENT_ADDRESS').toString()], #[groovy: return message.getInboundProperty('http.request').toString()], '');"></jdbc-ee:query>
</jdbc-ee:connector>
<flow name="log-request" doc:name="log-request">
<vm:inbound-endpoint path="log-request.in" />
<logger message="#[message.inboundProperties['user-agent']]" level="INFO" doc:name="Logger"/>
<jdbc-ee:outbound-endpoint exchange-pattern="one-way" queryKey="wsadb" responseTimeout="10000" queryTimeout="-1" connector-ref="jdbcConnector" doc:name="Persist raw message" />
</flow>
What it prints out is "null" and i dont know how to make it print the property from message...
No need to use Groovy:
<logger message="#[message.inboundProperties['user-agent']]" level="INFO" doc:name="Logger"/>
But your bigger issue is that you are not propagating the inbound properties to the outbound scope prior to dispatching to vm://log-request.in.
You need to propagate the properties you want to carry forward:
<scripting:transformer name="noopLoggingTransformer">
<scripting:script engine="groovy">
def props = [:]
props['User-Agent'] = message.getProperty('User-Agent', org.mule.api.transport.PropertyScope.INBOUND)
muleContext.client.dispatch('vm://log-request.in', payload, props)
message
</scripting:script>
</scripting:transformer>
Of course, you can iterate the inbound property names to copy them all.
Property name is User-Agent and as David pointed out, #message.inboundProperties['User-Agent']] is the MEL way to get it.
Did you make sure User-Agent property is set on the mule message when you're trying to access it. It's not always there
Remember inbound properties are not propagated unless you copy property manually like by
<copy-properties propertyName="*"/>