Making WebMQ Synchronous - mule

I'm trying to make WebMQ act synchronously in MULE in order to turn the message queue into a REST api for an internal project. Unfortunately, I know very little about MULE.
After a good bit of work, I started understanding the Request-Reply scope and tried to use the WMQ Connector with it, only to find out that WMQ only sends once the flow has ended.
I've tried putting the request into a different flow using VM to trigger it
but so far that just leads to it waiting forever on WMQ that will never happen.
I've also tried using VMs for back and forth:
But it seems to do the same thing as without, where it just ignores the input.
Now I know the input and output for the WMQ are working, as I previously setup a flow that used http to communicate with itself and let it know when a message went through.
What I essentially want is this, but using HTTP instead of AJAX
My latest, and perhaps closest attempt looks like thus:
The XML being:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:http="http://www.mulesoft.org/schema/mule/http" version="EE-3.6.0" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:ajax="http://www.mulesoft.org/schema/mule/ajax" xmlns:core="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:stdio="http://www.mulesoft.org/schema/mule/stdio" xmlns:test="http://www.mulesoft.org/schema/mule/test" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:wmq="http://www.mulesoft.org/schema/mule/ee/wmq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/ajax http://www.mulesoft.org/schema/mule/ajax/current/mule-ajax.xsd
http://www.mulesoft.org/schema/mule/ee/wmq http://www.mulesoft.org/schema/mule/ee/wmq/current/mule-wmq-ee.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/stdio http://www.mulesoft.org/schema/mule/stdio/current/mule-stdio.xsd
http://www.mulesoft.org/schema/mule/test http://www.mulesoft.org/schema/mule/test/current/mule-test.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd">
<wmq:connector channel="MAGENTO.SVRCONN" doc:name="WMQ Connector" hostName="[ip]" name="wmqConnector" port="1414" queueManager="MAGENTO" transportType="CLIENT_MQ_TCPIP" validateConnections="true" />
<vm:connector name="VM" validateConnections="true" doc:name="VM">
<vm:queue-profile maxOutstandingMessages="500">
<default-persistent-queue-store/>
</vm:queue-profile>
</vm:connector>
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="Input">
<http:listener config-ref="HTTP_Listener_Configuration" path="/mq" doc:name="HTTP"/>
<set-payload value="#[message.inboundProperties.'http.query.params'.xml]" doc:name="Set Payload"/>
<logger message="Entering Request-Reply Payload: #[payload]" level="INFO" doc:name="Logger"/>
<request-reply doc:name="Request-Reply">
<vm:outbound-endpoint exchange-pattern="one-way" path="mq" connector-ref="VM" doc:name="VM_TriggerSend" />
<vm:inbound-endpoint exchange-pattern="request-response" path="mq-return" connector-ref="VM" doc:name="VM_Receive" />
</request-reply>
<logger message="Request-Reply has ended. Payload: #[payload]" level="INFO" doc:name="Logger"/>
</flow>
<flow name="Send_Message">
<vm:inbound-endpoint exchange-pattern="one-way" path="mq" connector-ref="VM" doc:name="VM_Send"/>
<logger message="(Preparing to Dispatch) Payload: #[payload]" level="INFO" doc:name="Logger"/>
<wmq:outbound-endpoint queue="PUT_QUEUE" connector-ref="wmqConnector" doc:name="WMQ"/>
<logger message="Message presumably being dispatched after this log" level="INFO" doc:name="Logger"/>
</flow>
<flow name="Receive_Message">
<wmq:inbound-endpoint queue="GET_QUEUE" connector-ref="wmqConnector" doc:name="WMQ_Receive" />
<logger message="Triggering Receive" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="request-response" path="mq-return" connector-ref="VM" doc:name="VM_TriggerReceive" />
</flow>
</mule>
Which almost works, but it hangs indefinitely without sending a response back to the HTTP server. Setting the vm:inbound-endpoint in the Request-Reply flow to one-way keeps it from hanging, but doesn't send the new payload that's been received, but instead the previous payload (as if it's being skipped over).
Any help at all would be greatly appreciated!

If I understood correctly you are just trying to expose a request on a queue and a response on a well known queue as a REST api.
There is no need of VM queues there, and neither request-reply elements as the JMS transport can simulate the request response exchange pattern.
JMS queues are just one way. You have to necesarily reply on a different queue. The logic behind a request-response scenario is an outbound-endpoint that having an outbound property: MULE_REPLYTO. This property should be set with the name of your well known reply to queue: GET_QUEUE (if no such header is provided a temporary queue will be created).
The MULE_REPLY to header will become the standard JMSReplyTo when the mesasge is received at the service. The service has to honor this header sending the reply back to that queue. If the service is implemented on Mule this will happen automatically, otherwise it might not happen. You should double check its being honored.
If you want to use a request-reply scope with to one-way endpoints rather than one request-reponse endpoint, it is fine, should work the same but with more code.

Making an Asynchronous datasource Synchronous can indeed be tricky. But I don't really see an issue with your request-reply strategy.
Try to use an request-reply with WMQ endpoint on both sides. Then monitor the queues and see that the message and reply arrives as they should. Do you use the same queue for the request and the reply? The simplest scenario would be to use different ones, is that possible for your use-case?

Related

How to get Client IP from UDP Transport in Mule ESB?

I'm trying to get the client IP and socket of a UDP package and save it in a Flowvar variable using the MEL code
#[message.inboundProperties.MULE_REMOTE_CLIENT_ADDRESS]
However this variable is always null, I have been able to make it work on TCP transport, does anyone know how to get the remote client address in UDP?
This is my XML file:
<mule xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata" xmlns:udp="http://www.mulesoft.org/schema/mule/udp" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/udp http://www.mulesoft.org/schema/mule/udp/current/mule-udp.xsd
http://www.mulesoft.org/schema/mule/amqp http://www.mulesoft.org/schema/mule/amqp/current/mule-amqp.xsd">
<udp:connector name="UDP" validateConnections="true" keepSendSocketOpen="true" doc:name="UDP" broadcast="true"/>
<flow name="udpFlow">
<udp:inbound-endpoint exchange-pattern="one-way" host="172.22.20.103" port="4040" connector-ref="UDP" responseTimeout="10000" doc:name="UDP" metadata:id="9260547c-3b58-4ebd-953e-fd3e7bb063f3"/>
<object-to-string-transformer doc:name="Object to String"/>
<set-variable variableName="source" value="#[message.inboundProperties.MULE_REMOTE_CLIENT_ADDRESS]" metadata:id="6a72ad72-167f-44da-9f3d-75143c5c0a2f" doc:name="Variable"/>
<set-payload value="#[flowVars.source] dice #[payload]" doc:name="Set Payload"/>
<echo-component doc:name="Echo"/>
</flow>
</mule>
UPDATE:
I solve the Address issue with the MEL code
#[message.inboundProperties['packet.address']]: #[message.inboundProperties['packet.port']]
Thanks to David Dossot for his help.
Use:
#[message.inboundProperties['packet.address']]

Mule JMS Topic and ActiveMQ Configuration

I am using Mule ESB to design a process whereby one can post a message to a topic. Subscribers will listen to the topic and receive messages. Each subscriber will act on the messages differently. The goal here is to have the ability to post a test message to the topic from HTTP for testing subscribers.
Here is how I have the JMS connection configured:
<!-- JMS Topic connector -->
<jms:activemq-connector name="jmsTopicConnection" specification="1.1" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ2" durable="true" numberOfConcurrentTransactedReceivers="2"/>
This is the flow:
<flow name="auditJMSServiceFlow">
<http:listener config-ref="HTTP" path="/Audit/Activity" responseStreamingMode="ALWAYS" doc:name="HTTP"/>
<set-variable variableName="#['id']" value="#[message.inboundProperties['id']]" doc:name="set dynamic id"/>
<set-payload value="===TOPIC===" doc:name="Set Payload" />
<request-reply storePrefix="mainFlow">
<jms:inbound-endpoint topic="Audit.Activity" connector-ref="jmsTopicConnection" doc:name="JMS Topic Audit.Activity" exchange-pattern="request-response" durableName="audit_activity">
<jms:transaction action="ALWAYS_BEGIN" />
<!-- Not required to explicitly have this element. Mule will put this in implicitly. -->
<!-- <jms:jmsmessage-to-object-transformer displayName="JmsMsg to Object"/> -->
</jms:inbound-endpoint>
</request-reply>
<json:object-to-json-transformer doc:name="transform JMS message to JSON"/>
<json:validate-schema schemaLocation="resource://AuditMsgSchema.json" doc:name="Validate Json Schema"/>
<component class="com.baml.panther.audit.service.impl.AuditServiceImpl" doc:name="Java"/>
<default-exception-strategy>
<commit-transaction exception-pattern="com.foo.ExpectedExceptionType"/>
<jms:outbound-endpoint queue="dead.letter" connector-ref="jmsConnection">
<jms:transaction action="JOIN_IF_POSSIBLE" />
</jms:outbound-endpoint>
</default-exception-strategy>
<logger message="=== #[message.payload] received #[org.mule.util.DateUtiles.getTimeStamp('dd-MM-yyyy_HH-mm-ss.SSS')]" level="INFO" doc:name="Logger"/>
When I am running through the test I get the following error:
Any suggestions would be greatly appreciated.
Russ
For the error: Your request-reply scope is missing an outbound endpoint. You only have the inbound-endpoint (jms:inbound-endpoint). You need to provide the outbound-endpoint as well.
<request-reply storePrefix="mainFlow">
<jms:inbound-endpoint topic="Audit.Activity" connector-ref="jmsTopicConnection" doc:name="JMS Topic Audit.Activity" exchange-pattern="request-response" durableName="audit_activity">
<jms:transaction action="ALWAYS_BEGIN" />
<!-- Not required to explicitly have this element. Mule will put this in implicitly. -->
<!-- <jms:jmsmessage-to-object-transformer displayName="JmsMsg to Object"/> -->
</jms:inbound-endpoint>
</request-reply>
Not sure what your aim there but if you put just a jms:outbound-enpoint (instead of the whole request-reply block), you can send a message to the JMS topic.
The problem is that you cannot put a message source as the first message processor in a request-reply. The request reply allows you a kind of synchronous call for async protocols like JMS.
If you want to send a message to the message broker at the point where you put the request-reply just put a JMS outbound-endpoint.
If what you want to do is consume a message from the JMS topic you have to put a JMS inbound endpoint as the first message processor in a flow.

How to Intercept incoming call in Mule

Hi I am working with Mule Any Point platform i am using composite source which is listening from HTTP and JMS both. I want to identify the incoming call coming from HTTP or JMS and i want to print using the logger. How to do that ?
Try the following way of using logger inside your endpoints.
<composite-source doc:name="Composite Source">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP">
<logger message="Request coming from HTTP endpoint."></logger>
<set-variable value="HTTP" variableName="myVar"></set-variable>
</http:inbound-endpoint>
<jms:inbound-endpoint doc:name="JMS" queue="in">
<logger message="Request coming from JMS endpoint."></logger>
<set-variable value="JMS" variableName="myVar"></set-variable>
</jms:inbound-endpoint>
</composite-source>
In the flow when you have to chekc a condition, you can use the flow variable "myVar" to check whether the message came from HTTP or JMS endpoint.
Hope this helps.

Using Mule instances in a master/slave or failover relationship

I have two Mule instances subscribed to the same topic on a queue but I only want each message consumed once.
I can achieve this by funneling messages to unique queue and processing from there, but to reduce the operational complexity I want to set up the message consumer flow running on each Mule instance to defer to one of the instances.
This would be akin to an ActiveMQ failover setup (where only one instance is running at a time and idle instances only awaken when the running instance fails to respond) or a master/slave arrangement where I would grant one of the instances command over the others. Or like a VM transport that is inter-instance instead of intra-instance.
This would need to be done without any Mule Enterprise Edition components (relying only upon Mule Community Edition components) using Mule versions 3.4. or 3.5.
I was unable to find a convenient built-in way to do this. Instead I assume that each mule instance will run on a separate box and use the server.host value to determine which instance does the processing:
<mule xmlns:redis="http://www.mulesoft.org/schema/mule/redis"
xmlns="http://www.mulesoft.org/schema/mule/core"
version="CE-3.5.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/redis http://www.mulesoft.org/schema/mule/redis/3.4/mule-redis.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd">
<!-- define redis instance -->
<redis:config name="redis-instance" />
<flow name="topicConsumer">
<!-- listen to redis channel (topic) -->
<redis:subscribe config-ref="redis-instance">
<redis:channels>
<redis:channel>topic.channel</redis:channel>
</redis:channels>
</redis:subscribe>
<!-- save original payload (message from Redis) -->
<set-session-variable variableName="redisPayload" value="#[payload]" />
<!-- select processor -->
<flow-ref name="topicProcessorSelector"/>
<choice>
<when expression="#[sessionVars['subscriberProcessor'] == server.host]">
<logger level="INFO" message="processing on #[server.host]"/>
</when>
<otherwise>
<logger level="INFO" message="take no action"/>
</otherwise>
</choice>
</flow>
<flow name="topicProcessorSelector" processingStrategy="synchronous">
<!-- get key -->
<redis:get config-ref="redis-instance"
key="topic_processor"/>
<!-- if no key, then add this instance as the processor -->
<choice>
<when expression="#[payload instanceof org.mule.transport.NullPayload]">
<!-- set key -->
<redis:set config-ref="redis-instance"
key="topic_processor"
expire="10"
value="#[server.host]">
</redis:set>
<set-session-variable variableName="subscriberProcessor" value="#[server.host]" />
</when>
<otherwise>
<!-- use existing key -->
<byte-array-to-string-transformer/>
<set-session-variable variableName="subscriberProcessor" value="#[payload]" />
</otherwise>
</choice>
</flow>
</mule>

editing response in mule flow before it gets sent back to the request-response endpoint

I'm kinda new to mule esb, and I can't resolve one trouble I got. Here is what happens:
I have a flow in mule 3.2.0, which receives object with request to a ws. I send it to ws with cxf:jaxws-client and. At the beginning of this flow I have vm:inbound endpoint with request-response pattern. What I want is to apply transformation to the object returned as response from the "vmIn endpoint" before it gets send back to the caller from the "vm.logService endpoint" of the flow. I actually get the response, but it's null payload. The "vm.logService" is the endpoint to witch I send MuleMessage from the Java code with MuleClient.send(url, message, properties).I've read that this should be done with the "response" block, but it seems that this is not happening.
Here is my configuration
<vm:endpoint name="vmOut" path="vmOut" exchange-pattern="request-response"/>
<vm:endpoint name="vmIn" path="vmIn" exchange-pattern="request-response"/>
<pattern:web-service-proxy
name="name"
inboundEndpoint-ref="vmIn"
transformer-refs="logging"
responseTransformer-refs="logging"
outboundEndpoint-ref="vmOut" />
<flow name="logService">
<vm:inbound-endpoint path="vm.logService"/>
<vm:outbound-endpoint ref="vmIn">
<cxf:jaxws-client serviceClass="my.WSClass" operation="operation"
enableMuleSoapHeaders="false"/>
<object-to-string-transformer/>
</vm:outbound-endpoint>
<response>
<custom transformer name="myTransformer" class="someclass" />
</response>
<flow name="genericTransformer">
<vm:inbound-endpoint path="vmOut"/>
<custom-transformer class="mypkg.GenericServiceTransformer">
</custom-transformer>
</flow>
<flow name="import">
<vm:inbound-endpoint path="vm.import" exchange-pattern="request-response"/>
<http:outbound-endpoint address="${Service}" responseTimeout="${ws.timeout}" exchange-pattern="request-response" />
<object-to-string-transformer/>
</flow>
Well, after sending with jaxws-client I have few more flows where this request message is processed, but I don't think that this is the reason why it's not working. Thanks in advance for any help
The "vm.logService" VM endpoint doesn't look request-response to me: since you don't specify an exchange pattern, it is actually one-way by default. That could explain why you don't get anything back.
Also we don't see the definition of the "vmIn" so we can't be sure it's correctly request-response, which could be another reason for not reaching the response block.
Actually: if your response block is the last element in the flow, you don't need it: it's OK if "myTransformer" is applied in the request phase since there's nothing after.
after sending with jaxws-client I have few more flows where this request message is processed
I really don't understand what you mean by that.