Maintaining Mule Message - java

Similar to this discussion Maintain Payload State during mule flow execution
I would like to know how to maintain an entire Mule Message throughout my flow.
I am trying to call a jersey resource component after I have received information that the user is authorized to call it. In this authorization request the payload and original http request gets altered.
My predicament is that I don't want to call the resource first as that would be inefficient and insecure however I cannot see any other plausible way to do this.
<flow name="test">
<http:inbound-endpoint exchange-pattern="request-response" host="0.0.0.0" port="1234" path="test" doc:name="HTTP"/>
<!-- sub-flow here which changes the MuleMessage and loses all original inbound properties -->
<jersey:resources doc:name="REST">
<component class="com.Test" />
</jersey:resources>
</flow>
Thanks for any help in advance

Mule 3 includes two scopes that will allow you to preserve the original message, while executing other message processors:
If you must wait for the sub-flow to complete because you need to use information produced by the sub-flow, use a message enricher like so. This example assigns the variable "authorized" to whatever the payload is once the sub-flow finishes processing the message.
<enricher target="#[variable:authorized]">
<flow-ref name="checkAuthorization" />
</enricher>
If you do not need to wait for the sub-flow to complete before allowing your Jersey Resource to run, use the async scope like so:
<async>
<flow-ref name="goForthAndDoSomething" />
</async>

There are multiple ways to save a mule message and it's properties so that it could be retrieve when required .. In your case you could save the entire Mule message in a variable and retrieve it when required for example :
<flow name="test">
<http:inbound-endpoint exchange-pattern="request-response" host="0.0.0.0" port="1234" path="test" doc:name="HTTP"/>
<!-- You save your entire message in a session variable named entireMessage before calling a subflow-->
<set-session-variable variableName="entireMessage" value="#[message.payload]" />
<!-- You can now call your Sub flow -->
<jersey:resources doc:name="REST">
<component class="com.Test" />
</jersey:resources>
</flow>
Here in the above flow you store your Mule message in a session variable named entireMessage .. You can easily retrieve the value of this session variable whenever you need in any flow anywhere like the following :-
<logger level="INFO" message="#[sessionVars['entireMessage']]"/>
This will print you Mule message
There is also an alternative way to store the http headers before it get altered ..
you can also use the following :-
<flow name="test">
<http:inbound-endpoint exchange-pattern="request-response" host="0.0.0.0" port="1234" path="test" doc:name="HTTP"/>
<!-- You copy all the HTTP headers before calling a subflow-->
<copy-properties propertyName="http.*" doc:name="Copy All HTTP Headers"/>
<!-- You can now call your Sub flow -->
<jersey:resources doc:name="REST">
<component class="com.Test" />
</jersey:resources>
</flow>
The above flow will copy all the HTTP headers before calling any other flow
UPDATED FLOW :-
If you need the original unaltered payload for your Jersy component , please overwrite the current payload with the original payload stored in session variable using set payload component
<flow name="test">
<http:inbound-endpoint exchange-pattern="request-response" host="0.0.0.0" port="1234" path="test" doc:name="HTTP"/>
<!-- You save your entire message in a session variable named entireMessage before calling a subflow-->
<set-session-variable variableName="entireMessage" value="#[message.payload]" />
<!-- You can now call your Sub flow -->
<!-- overwrite current payload with original unaltered payload -->
<set-payload value="#[sessionVars['entireMessage']]" doc:name="Set Payload"/>
<jersey:resources doc:name="REST">
<component class="com.Test" />
</jersey:resources>
</flow>

Try somthing like this to store the original message in session:
<message-properties-transformer scope="session" doc:name="Save original message">
<add-message-property key="originalMessage" value="#[message:payload]"></add-message-property>
</message-properties-transformer>
Then try something like this to get it from session:
<expression-transformer evaluator="..." expression="SESSION:originalMessage" doc:name="Restore original message"></expression-transformer>

Thanks for all your help. The final solution answer was:
<flow name="test">
<http:inbound-endpoint exchange-pattern="request-response" host="0.0.0.0" port="1234" path="test" doc:name="HTTP"/>
<enricher target="#[variable:unwantedPayload]" source="#[payload]">
<flow-ref name="anotherFlowCalled" />
</enricher>
<jersey:resources doc:name="REST">
<component class="com.Test" />
</jersey:resources>
</flow>

best way to store the mule message into session , whether you flow contains subflows are private flow session vars carry till end of the execeution.

Related

Will this quartz connector I configured pick only one file at a time

This is the mule config file for a service of a class , that basically reads order file and processes it. Sometime the code is confused and it processes two or more file and getting freezed. I want the code to read only one file at a time.
<quartz-connector name = "oneThreadQuartzConnector">
<quartz:factory-property key ="org.quartz.threadpool.threadcount" value="1"/>
</quartz-connector>
<service name="Retail Transfer Request Service">
<inbound>
<file:inbound-endpoint path="#{es.dir.008}" moveToDirectory="#{es.dir.008}/archive/ORD">
<file:filename-wildcard-filter pattern="OR*" />
</file:inbound-endpoint>
</inbound>
<component>
<spring-object bean="retailTransferRequestAction" />
</component>
<default-service-exception-strategy>
<vm:outbound-endpoint path="found.error.queue" />
</default-service-exception-strategy>
</service>
The quartz will pick data one by one if you want to make a synchronous call the best option is to choose processing strategy in the flow and make it synchronous
<flow name="sampleFlow" processingStrategy="synchronous">

Is there any bug in showing "Number Of Pending Messages" in ACTIVE MQ?

We are using active mq with Mule ESB JMS for our webservices. It is working fine. But the problem is, even the request is forwarded to my services from queue, processed and giving the response back, but still in the Active MQ web console, Number Of Pending Messages showing the total no.of requests.
Web Console ::
Flow diagram,
Flow in Mule is ::
<jms:activemq-connector name="Active_MQ" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
<flow name="vbrtestmulejmsFlow1" doc:name="vbrtestmulejmsFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8888" doc:name="HTTP" path="AMServices">
<set-property propertyName="Content-Type" value="text/xml"/>
</http:inbound-endpoint>
<object-to-string-transformer doc:name="Object to String" mimeType="text/xml"/>
<jms:outbound-endpoint queue="servicesQueue" connector-ref="Active_MQ" doc:name="JMS" responseTimeout="1000000" mimeType="text/xml" >
</jms:outbound-endpoint>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="5050" path="MyServices" method="POST" doc:name="HTTP" contentType="text/xml">
<set-property propertyName="Content-Type" value="text/xml"/>
</http:outbound-endpoint>
</flow>
Your flow sends the message received by the inbound HTTP endpoint to both the JMS outbound endpoint and the HTTP outbound endpoint.
So it's expected that the servicesQueue will contain 6 messages and that at the same time MyServices gets called 6 times.
Your intention is unclear but if what you wanted instead was to have servicesQueue act as an intermediary between the inbound and outbound HTTP endpoints then you need to cut your flow in two:
<flow name="AMServiceToQueue">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost"
port="8888" path="AMServices">
<set-property propertyName="Content-Type" value="text/xml"/>
</http:inbound-endpoint>
<object-to-string-transformer mimeType="text/xml"/>
<jms:outbound-endpoint queue="servicesQueue" connector-ref="Active_MQ"
exchange-pattern="request-response" responseTimeout="1000000" />
</flow>
<flow name="QueueToMyServices">
<jms:inbound-endpoint queue="servicesQueue" connector-ref="Active_MQ"
exchange-pattern="request-response" />
<http:outbound-endpoint exchange-pattern="request-response" host="localhost"
port="5050" path="MyServices" method="POST" contentType="text/xml">
<set-property propertyName="Content-Type" value="text/xml"/>
</http:outbound-endpoint>
</flow>

Mule session-variable missing from the message, when reading from JMS Queue inside a Component

I have requirement where in I need to read message from a JMS Queue from inside a Component.
But during this process the session variables associated with the message are missing.
But the session variables are available when the same message is read from JMS:inbound-endpoint instead of from inside a component.
Here are my sample flows.
Main flow sets a session-variable into MuleMessage and posts it onto a JMS:outbound-endpoint
<flow name="main-flow" >
<some inbound>
...
< Some processing >
<set-session-variable .... />
...
<jms:outbound-endpoint queue="myQueue1">
</flow>
When the message is read from a JMS:inbound-endpoint the session variable can be seen in the message.
<flow name="second-flow" >
<jms:inbound-endpoint queue="myQueue1" />
<logger level="INFO" />
...
< some processing />
</flow>
But when the message is read from the Component polling the JMS:queue the session variable is missing.
<flow name="third-flow" >
<quartz:inbound-endpoint repeat-interval="5 mins" />
....
<component>
<spring-object bean="MyComponent"/>
</component>
....
</flow>
MyComponent class's onCall method has the following code to read from the JMS queue.
String reqURL = "jms://" + queueName ;
muleMessage = eventContext.requestEvent(reqURL, 1000);
But the session variable is not present in the Mule Message.

Why am I not getting the changed payload after consuming JMS queue in Mule?

i've made a flow with JMS using ActiveMQ, i send a message to the queue, but for any reason when im trying to consume from the queue, get the message and change it by setting the new payload, it doesn't change. What am i doing wrong?
Basically i want to send back the changed payload through HTTP response
Here's my code:
<jms:activemq-connector name="Active_MQ"
specification="1.1"
brokerURL="tcp://localhost:61616"
validateConnections="true"
doc:name="Active MQ"
persistentDelivery="true"
/>
<flow name="jmsFlow1" doc:name="jmsFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="jms" doc:name="HTTP"/>
<set-payload value="#['This is a message test']" doc:name="Set Payload"/>
<choice doc:name="Choice">
<when expression="#[true]">
<processor-chain>
<logger message="Im here!!" level="INFO" doc:name="Logger"/>
<jms:outbound-endpoint queue="StudioIN" connector-ref="Active_MQ" doc:name="JMS Queue Studio IN" exchange-pattern="request-response"/>
</processor-chain>
</when>
</choice>
<logger message="#[payload]" level="INFO" category="//// RETURNED FROM QUEUE PAYLOAD" doc:name="Logger"/>
</flow>
<flow name="fmsAdapterConsumerFlow1" doc:name="fmsAdapterConsumerFlow1">
<jms:outbound-endpoint queue="StudioIN" connector-ref="Active_MQ" doc:name="JMS StudioIN Consumer" exchange-pattern="request-response"/>
<set-payload value="#[payload + ' returned from queue']" doc:name="Set Payload"/>
</flow>
You don't specify the exchange-pattern on the jms:outbound-endpoint and jms:inbound-endpoint. Therefore Mule uses the default, which is one-way. So it's impossible that the payload change made in fmsAdapterConsumerFlow1 get replied to jmsFlow1.
Set exchange-pattern="request-response" on both JMS endpoints and also set disableTemporaryReplyToDestinations="false" on the connector otherwise you'll never receive any response.
The second flow mentioned above is to be changed.
This flow starts with a inbound-endpoint if it has to read a message and process it.
<flow name="fmsAdapterConsumerFlow1" doc:name="fmsAdapterConsumerFlow1">
<jms:inbound-endpoint queue="StudioIN" connector-ref="Active_MQ" doc:name="JMS StudioIN Consumer" exchange-pattern="request-response"/>
<set-payload value="#[payload + ' returned from queue']" doc:name="Set Payload"/>
</flow>
Hope this helps.

How to expose a web-service with cxf:proxy-service

I am trying to expose a simple greeting web-service using "cxf:proxy-service" in mule. Given below is my flow.
<flow name="WS_In">
<http:inbound-endpoint address="http://localhost:8080/HelloService" exchange-pattern="request-response">
<cxf:proxy-service wsdlLocation="classpath:HelloService.wsdl" namespace="http://example.org/HelloService"/>
</http:inbound-endpoint>
<component>
<prototype-object class="com.example.ServiceProxy">
</prototype-object>
</component>
<echo-component></echo-component>
<logger level="INFO" />
</flow>
But it giving me error as below:
2013-01-03 16:13:35,569 ERROR [main] construct.AbstractFlowConstruct (AbstractFlowConstruct.java:180) - Failed to stop service: WS_In
org.mule.api.lifecycle.LifecycleException: Lifecycle Manager 'WS_In.stage1' phase 'start' does not support phase 'dispose'
My ServiceProxy calss is as below
public class ServiceProxy implements Callable, Initialisable
Please help me understand where I am missing the path.
Instead of attribute 'name' in <cxf:proxy-service> element, use attribute 'service' to specify service name.
Try this out ...
Get the service name from your WSDL and use it in cxf:proxy-service
User the class direclty in component.
....
<flow name="WS_In">
<http:inbound-endpoint address="http://localhost:8080/HelloService" exchange-pattern="request-response">
<cxf:proxy-service wsdlLocation="classpath:HelloService.wsdl" namespace="http://example.org/HelloService" service="HelloService"/>
</http:inbound-endpoint>
<component class="com.example.ServiceProxy" />
<echo-component></echo-component>
<logger level="INFO" />
</flow>

Categories

Resources