Aggregate two JMS messages from two different consumers - jms

I have two jms consumers, each in a different flow. I want to use another flow to aggregate the messages of thoe two messages. and also need to keep the correlation Ids as i need to split the payload and send back the messages.
<flow name="integration-consumer-client1" doc:name="integration-consumer-client1">
<jms:inbound-endpoint doc:name="JMS" connector-ref="Active_MQ" queue="client1.publish"/>
<logger message="Consumes Client One = #[payload]" level="INFO" doc:name="Logger"/>
<logger message="Client One Correlation = #[message.correlationId]" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="client1" doc:name="VM"/>
</flow>
<flow name="integration-consumer-client2" doc:name="integration-consumer-client2">
<jms:inbound-endpoint doc:name="JMS" connector-ref="Active_MQ" queue="client2.publish"/>
<logger message="Consumes Client Two = #[payload]" level="INFO" doc:name="Logger"/>
<logger message="Client Two Correlation = #[message.correlationId]" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="client2" doc:name="VM"/>
</flow>
<flow name="integration-internetsolutionsFlow1" doc:name="integration-internetsolutionsFlow1">
<scatter-gather doc:name="Scatter-Gather">
<vm:inbound-endpoint exchange-pattern="one-way" path="client1" doc:name="VM"/>
<vm:inbound-endpoint exchange-pattern="one-way" path="client2" doc:name="VM"/>
</scatter-gather>
</flow>
I tried to use the scatter gather with two inbound VMs but get the following error:
Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'vm:inbound-endpoint'. One of '{"http://www.mulesoft.org/schema/mule/core":annotations, "http://www.mulesoft.org/schema/mule/core":custom-aggregation-strategy, "http://www.mulesoft.org/schema/mule/core":threading-profile, "http://www.mulesoft.org/schema/mule/core":abstract-message-processor, "http://www.mulesoft.org/schema/mule/core":abstract-outbound-endpoint, "http://www.mulesoft.org/schema/mule/core":abstract-mixed-content-message-processor}' is expected.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)

The reason of the error is integration-internetsolutionsFlow1 doesn't have any inbound endpoint ..
What you can do is following :-
Use vm:outbound-endpoint to same path from both the flow
integration-consumer-client1 and integration-consumer-client2
Then in integration-internetsolutionsFlow1
<flow name="integration-internetsolutionsFlow1" doc:name="integration-internetsolutionsFlow1">
<vm:inbound-endpoint exchange-pattern="request-response" path="Your Path" doc:name="VM" connector-ref="vmConnector" />
<logger level="INFO" message="#[message.payload]" doc:name="Logger"/>
<!-- you don't require a setter-getter here -->
</flow>
The path of outbound VM from both the flow integration-consumer-client1 and integration-consumer-client2 should be same..
You no need a scatter-gather here .. since both the flow will disptch the payload to same VM path .. It will be receive by VM inbound endpoint

Related

Mule Https request response timeout

Im trying to config a response timeout for https request component.
My http connector is calling a URL, I want to set a time for example after 5 second if there is no response back from the URL close this https connection.
But I've been searched on google and mule site there are no related information.
This webservice i am calling resets password, if after certain time I don't get response I want to close it and DO NOT want to reset it.
Here is the sample code:
<http:request-config name="HTTP_Request_Configuration" protocol="HTTPS" host="10.255.255.1." port="2446" doc:name="HTTP Request Configuration" responseTimeout="1" usePersistentConnections="false">
The responseTimeout is not doing anything, I've tried using SOAPUI to test the time is still the same no matter what I put.
Thanks in advance
I have set the responseTimeout property in the Http- request config and it works for me.
Please find the code below
<!--Http Listener Config for calling Service-->
<http:listener-config name="HTTP_Listener_Configuration1" host="0.0.0.0" port="8092" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration" host="localhost" port="8092" doc:name="HTTP Request Configuration" responseTimeout="5000"/>
<flow name="testtimeoutFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="/test" method="GET" doc:name="HTTP"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="#[message.exception]" level="INFO" doc:name="Logger"/>
<set-payload value="#['Time out Error']" doc:name="Set Payload"/>
</catch-exception-strategy>
</flow>
<!-- Flow which has delay in responding the data-->
<flow name="testtimeoutFlow1">
<http:listener config-ref="HTTP_Listener_Configuration1" path="/test" doc:name="HTTP" allowedMethods="GET"/>
<set-payload value="#['HelloWorld']" doc:name="Set Payload"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<!-- Delay for 10 seconds-->
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[sleep(10000);
return message.payload;]]>
</scripting:script>
</scripting:component>
<logger message="After Script : #[payload]" level="INFO" doc:name="Logger"/>
</flow>
Hope this helps.

How to Transform JMS message to JSON for DataMapper

I am sending the following json message to a flow via JMS:
[{"salesOrderId":"00001-2-3","saleName":"Car Sale","status":"processing"}, {"salesOrderId":"00004-5-6","saleName":"House Sale","status":"processing"}]
this is my strategy:
<flow name="integration-consumer-client2" doc:name="integration-consumer-client2">
<jms:inbound-endpoint queue="client2.queue" connector-ref="Active_MQ" doc:name="JMS"/>
<logger message="Consumes Client 2 = #[payload]" level="INFO" doc:name="Logger"/>
<logger message="Client 2 Correlation = #[message.correlationId]" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="response" doc:name="VM"/>
</flow>
<flow name="integration-consumer-client" doc:name="integration-consumer-client">
<jms:inbound-endpoint doc:name="JMS" connector-ref="Active_MQ" queue="client1.queue">
</jms:inbound-endpoint>
<logger message="Consumes Client = #[payload]" level="INFO" doc:name="Logger"/>
<logger message="Client Correlation = #[message.correlationId]" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="response" doc:name="VM"/>
</flow>
<flow name="integration-flow" doc:name="integration-flow">
<vm:inbound-endpoint path="response" doc:name="VM">
<message-properties-transformer>
<add-message-property key="MULE_CORRELATION_GROUP_SIZE" value="2" />
</message-properties-transformer>
<collection-aggregator/>
</vm:inbound-endpoint>
<logger message="after vm = #[payload]" level="INFO" doc:name="Logger"/>
<request-reply doc:name="Request-Reply">
<jms:outbound-endpoint queue="queue.validation" connector-ref="Active_MQ" doc:name="JMS">
<jms:object-to-jmsmessage-transformer doc:name="Object to JMSMessage"/>
</jms:outbound-endpoint>
<jms:inbound-endpoint queue="queue.validation.response" connector-ref="Active_MQ" doc:name="JMS"/>
</request-reply>
<logger message="Siebel Response in ESB = #[payload]" level="INFO" doc:name="Logger"/>
</flow>
So two consumers messages are aggregated and then sent to another flow via the request reply using JMS. in that flow the message comes through as
[{"salesOrderId":"00001-2-3","saleName":"Car Sale","status":"processing"}, {"salesOrderId":"00004-5-6","saleName":"House Sale","status":"processing"}]
and the flow:
<jms:activemq-connector name="Active_MQ" username="admin" password="admin" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
<data-mapper:config name="JSON_To_JSON" transformationGraphPath="json_to_json.grf" doc:name="JSON_To_JSON"/>
<flow name="validation-flow" doc:name="validation-flow">
<jms:inbound-endpoint doc:name="JMS" connector-ref="Active_MQ" queue="queue.validation" >
<jms:jmsmessage-to-object-transformer doc:name="JMSMessage to Object"/>
</jms:inbound-endpoint>
<logger message="Payload = #[payload]" level="INFO" doc:name="Logger"/>
<data-mapper:transform config-ref="JSON_To_JSON" doc:name="JSON To JSON"/>
<logger message="inside siebel after mapper = #[payload]" level="INFO" doc:name="Logger"/>
</flow>
I want to send the data through a mapper because i would like to change the status to "Complete". but after the json to json mapper the result is [B#2b9f82b. How can i transform the jms message to be more readable for the mapper?
What you have is a perfectly valid bytearray. You can convert it to String again using a object-to-string-transformer or even better a byte-array-to-string-transformer.

How to aggregate inbound JMS messages in mule

I am receiving two JMS messages from activeMQ
<flow name="clientoneFlow1" doc:name="clientoneFlow1">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8081" path="client1" doc:name="HTTP"/>
<component class="SalesOrder" doc:name="Java"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<jms:outbound-endpoint queue="ReadOrder1" connector-ref="Active_MQ" doc:name="JMS">
<jms:object-to-jmsmessage-transformer doc:name="Object to JMSMessage"/>
</jms:outbound-endpoint>
</flow>
<flow name="clienttwoFlow1" doc:name="clienttwoFlow1">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8081" path="client2" doc:name="HTTP"/>
<component class="SalesOrder2" doc:name="Java"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<jms:outbound-endpoint queue="ReadOrder1" connector-ref="Active_MQ" doc:name="JMS">
<jms:object-to-jmsmessage-transformer doc:name="Object to JMSMessage"/>
</jms:outbound-endpoint>
</flow>
<flow name="integration-flow" doc:name="integration-Flow1" processingStrategy="synchronous">
<jms:inbound-endpoint queue="ReadOrder1" connector-ref="Active_MQ" doc:name="JMS"/>
<vm:outbound-endpoint exchange-pattern="request-response" path="vm" doc:name="VM"/>
<logger message="ending paylaod = #[payload]" level="INFO" doc:name="Logger"/>
</flow>
<flow name="integration-flow2" doc:name="integration-Flow2">
<vm:inbound-endpoint exchange-pattern="request-response" path="vm" doc:name="VM"/>
<collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator"/>
</flow>
How can I aggregate the incoming messages? I am using a collection-aggregator and i keep getting the message =
Correlation Group Size not set, but correlation aggregator is being used. Message is being forwarded as is
The Message is a JSON [{"salesOrderId":"00001-2-3","saleName":"Car Sale","status":"processing"}]
I see some issues in the flow .. In both the flows clientoneFlow1 and clienttwoFlow1 you are using http inbound endpoint and hitting the url separately to start the flows dispatch the message to queue="ReadOrder1" ..
But here as soon as the message is delivered to the queue="ReadOrder1" by one of the flow , integration-flow get started and the message to again dispatched to integration-flow2 where it is received by the collection-aggregator and it doesn't wait for the other flows to get the message (since you need to hit the url of other flow to start it)...
So.. here you could make both the flows clientoneFlow1 and clienttwoFlow1 to execute almost in parallel and dispatch the message to the collection-aggregator almost at a same time ..
So.. one way you can achieve it by using scatter and gather component and you don't required a collection-aggregator there ..
All the message from all the flows will be automatically aggregated at the end of the flow ..
for example ... here you can do the following :-
<flow name="fork" doc:name="fork">
<http:inbound-endpoint host="localhost" port="8090" path="scattergather" exchange-pattern="request-response" doc:name="HTTP"/>
<scatter-gather timeout="6000">
<!-- Calling clientoneFlow1-->
<flow-ref name="clientoneFlow1" doc:name="Flow Reference"/>
<!-- Calling clienttwoFlow1-->
<flow-ref name="clienttwoFlow1" doc:name="Flow Reference"/>
</scatter-gather>
<logger level="INFO" message="Combined Payload: #[message.payload]" doc:name="Logger"/>
<logger level="INFO" message="Payload1 of clientoneFlow1 : #[message.payload[0]] and clienttwoFlow1: #[message.payload[1]] " doc:name="Logger"/>
</flow>
<flow name="clientoneFlow1" doc:name="clientoneFlow1">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8081" path="client1" doc:name="HTTP"/>
<component class="SalesOrder" doc:name="Java"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
<flow name="clienttwoFlow1" doc:name="clienttwoFlow1">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8081" path="client2" doc:name="HTTP"/>
<component class="SalesOrder2" doc:name="Java"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
Now this is the easiest way to achieve combined payload from both the flows without making it so complex ..

How to use variable values from another flow on mule?

Im trying to access a value from session variable set into another flow
code:
<flow name="test" doc:name="test" >
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8081/services/autocomplete" connector-ref="" transformer-refs="transform" doc:name="HTTP">
</http:inbound-endpoint>
<set-variable variableName="req" value="#[message.inboundProperties['http.query.string']]" doc:name="Variable"/>
<set-session-variable variableName="message" value="test" doc:name="Set Message ID"/>
<http:outbound-endpoint host="teste.local" path="newlocation/autocomplete?#[groovy:return req.toString();]" port="8080" user="login" password="1234" exchange-pattern="request-response" doc:name="HTTP">
</http:outbound-endpoint>
</flow>
and another flow trying to print it:
<flow name="test2" doc:name="test2" >
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8081/services/autocomplete2" connector-ref="" transformer-refs="transform" doc:name="HTTP">
</http:inbound-endpoint>
<set-variable variableName="req" value="#[message.inboundProperties['http.query.string']]" doc:name="Variable"/>
<logger message="#[sessionVars.message]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint host="teste.local" path="newlocation/autocomplete?#[groovy:return req.toString();]" port="8080" user="login" password="1234" exchange-pattern="request-response" doc:name="HTTP">
</http:outbound-endpoint>
</flow>
But there is an error saing there is no variable set into that flow even when i first try to access the first url them i change to the seccond where it was supose to have the session.
-> mule version 3.4
Session variables need to be passed from one flow to another. They are serialized and deserialized on the event. You're setting it in the first flow and calling /autocomplete but the flow thats reading it is listening on /autocomplete2.
You cannot hit /autocomplete2 separately after /autocomplete and expect the session variable to be there as it was set on a different event. If you are looking to store state between separate flow invocations take a look at the mule objectstore module
http://mulesoft.github.io/mule-module-objectstore/mule/objectstore-config.html
And info on Mule object stores here:
http://www.mulesoft.org/documentation/display/current/Mule+Object+Stores
Some example configurations here:
https://github.com/mulesoft/mule-module-objectstore/blob/master/src/test/resources/mule-config.xml
Your flow will be something like the following :-
<flow name="test" doc:name="test" >
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8081/services/autocomplete" doc:name="HTTP">
</http:inbound-endpoint>
<set-variable variableName="req" value="#[message.inboundProperties['http.query.string']]" doc:name="Variable"/>
<set-session-variable variableName="message" value="test" doc:name="Set Message ID"/>
<logger message="Done #[sessionVars.message]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:8081/services/autocomplete2" doc:name="HTTP"/>
</flow>
<flow name="test2" doc:name="test2" >
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8081/services/autocomplete2" doc:name="HTTP">
</http:inbound-endpoint>
<set-variable variableName="req" value="#[message.inboundProperties['http.query.string']]" doc:name="Variable"/>
<logger message="#[sessionVars.message] #[sessionVars['message']] " level="INFO" doc:name="Logger"/>
</flow>

Magento Connector in Mule 3.5

I have tried creating Megento connector example program as given in the Megento connector vedio link.http://www.youtube.com/watch?v=GCbuqHLCiOg
My flow is:
<magento:config name="MagentoConnector" username="${magento.username}" password="${magento.password}" address="${magento.address}" doc:name="Magento">
<magento:connection-pooling-profile initialisationPolicy="INITIALISE_ONE" exhaustedAction="WHEN_EXHAUSTED_GROW"/>
</magento:config>
<flow name="ShoppingCartOPerations" doc:name="ShoppingCartOPerations">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="shoppingCartOperation" doc:name="HTTP"/>
<flow-ref name="CreateProduct" doc:name="Flow Reference"/>
<set-payload value="Product Id is #[groovy:message.getProperty('productId')]" doc:name="Set Payload"/>
</flow>
<sub-flow name="CreateProduct" doc:name="CreateProduct">
<magento:create-product config-ref="MagentoConnector" type="simple" set="1" sku="simple_sku" storeViewIdOrCode="4" doc:name="Create Product" address="https://sashistore.gostorego.com/api/v2_soap" password="gdskey" username="gdssrao">
<magento:attributes name="SampleProduct" description="TestProduct" short_description="creating sample product" weight="100" status="1" visibility="4" price="100" tax_class_id="1"/>
</magento:create-product>
<set-property propertyName="productId" value="#[payload]" doc:name="Store Product id"/>
<magento:update-inventory-stock-item config-ref="MagentoConnector" productId="#[groovy:message.getProperty('productId')]" doc:name="Update Stock">
<magento:catalog-inventory-stock-item qty="33" is_in_stock="100" min_qty="10"/>
</magento:update-inventory-stock-item>
</sub-flow>
ERROR 2014-01-29 23:48:48,521 [[magentotest].connector.http.mule.default.receiver.02] org.mule.retry.notifiers.ConnectNotifier: Failed to connect/reconnect: Work Descriptor. Root Exception was: null. Type: class org.mule.api.ConnectionException
ERROR 2014-01-29 23:48:48,524 [[magentotest].connector.http.mule.default.receiver.02] org.mule.exception.DefaultMessagingExceptionStrategy:
<magento:config name="MagentoConnector" username="gdssrao" password="gdskey" address="https://sashistore.gostorego.com/api/v2_soap" doc:name="Magento">
<magento:connection-pooling-profile initialisationPolicy="INITIALISE_ONE" exhaustedAction="WHEN_EXHAUSTED_GROW"/>
</magento:config>
<flow name="ShoppingCartOPerationsFlow" doc:name="ShoppingCartOPerationsFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="shoppingCartOperation" doc:name="HTTP"/>
<logger level="INFO" doc:name="Logger"/>
<flow-ref name="CreateProductFlow" doc:name="Flow Reference"/>
<logger level="INFO" doc:name="Logger"/>
<set-payload value="Product Id is #[groovy:message.getProperty('productId')]" doc:name="Set Payload"/>
</flow>
<sub-flow name="CreateProductFlow" doc:name="CreateProductFlow">
<magento:create-product config-ref="MagentoConnector" type="simple" set="1" sku="simple_sku" storeViewIdOrCode="4" doc:name="Create Product">
<magento:attributes name="SampleProduct" description="TestProduct" short_description="creating sample product" weight="100" visibility="4" />
</magento:create-product>
<logger level="INFO" doc:name="Logger"/>
<set-property propertyName="productId" value="#[payload]" doc:name="Store Product id"/>
<logger level="INFO" doc:name="Logger"/>
<magento:update-inventory-stock-item config-ref="MagentoConnector" productId="#[groovy:message.getProperty('productId')]" doc:name="Update Stock">
<magento:catalog-inventory-stock-item />
</magento:update-inventory-stock-item>
</sub-flow>
You have defined your plaintext connection attributes (username, password, address) in magento:create-product and then you have them as application properties in magento:config. That does not really make sense, as you only need to define the attributes once (in the config element) when you use config-ref in the other elements. Since you are having a connection failure, I would guess that you have incorrect properties in the config element. Try using the attributes from magento:create-product, instead.
EDIT: I checked the WSDL for your Magento API, and it seems that you have incorrect address
Try using https://sashistore.gostorego.com/index.php/api/v2_soap/index/ instead.
EDIT2: I got the WSDL URL for Magento API v2 from the Magento documentation. See this page for explanation on how to get the address for Web services from WSDL.

Resources