In Mule 3.4, how do I obtain the value of the Mule variable set from the "set-variable" tag in Java? Also how do I obtain values of Mule variables in different flows such as counter in flow1 and prevCounter in flow2? I can't find this on Mule's website.
Below is the Mule XML:
<mule xmlns:smtp="http://www.mulesoft.org/schema/mule/smtp" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" 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:mongo="http://www.mulesoft.org/schema/mule/mongo" xmlns:quartz="http://www.mulesoft.org/schema/mule/quartz" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:core="http://www.mulesoft.org/schema/mule/core" version="EE-3.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/mongo http://www.mulesoft.org/schema/mule/mongo/2.0/mule-mongo.xsd
http://www.mulesoft.org/schema/mule/quartz http://www.mulesoft.org/schema/mule/quartz/current/mule-quartz.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/http http://www.mulesoft.org/schema/mule/http/current/mule-http.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/smtp http://www.mulesoft.org/schema/mule/smtp/current/mule-smtp.xsd">
<quartz:connector name="Quartz3" validateConnections="true" doc:name="Quartz"/>
<flow name="flow1" doc:name="flow1">
<set-variable variableName="#['counter']" value="#[0]" doc:name="Variable"/>
<flow-ref name="flow2" doc:name="Flow Reference"/>
</flow>
<flow name="flow2" doc:name="flow2">
<logger level="INFO" doc:name="Logger"/>
<set-variable variableName="prevCounter" value="#[flowVars['counter']]" doc:name="Variable"/>
<set-variable variableName="counter" value="#[flowVars['counter']+1]" doc:name="Variable"/>
<choice doc:name="Choice">
<when expression="#[flowVars['counter']==5]">
<logger level="INFO" doc:name="Logger"/>
</when>
<otherwise>
<flow-ref name="flow2" doc:name="Flow Reference"/>
</otherwise>
</choice>
</flow>
</mule>
You can get them from the Mule message with message.getInvocationProperty('counter').
Flow variables exist only during the flow of a message, so you can only access what was declared before in the same flow (or the flow that calls the current flow like you are doing right there in flow2). If you need them somewhere outside of the flow, you have to send them there from the flow.
Values stored with set-variable can be retrieved with MEL as flowVars['varName'].
Take a look at this:
http://blogs.mulesoft.org/wp-content/uploads/2012/12/refcard-mel.pdf
Please try to create session variable or Flow variable in java and to retrive them in java MEL wont support you should use syntax some thing like message.getInvocationProperty('name') if those are flow variables.
Related
I am trying to convert SFTP byte payload to java using dataweave so I can loop through the input records using an existing flow. How do I do this?
I have set it to java in Dataweave and preview shoulds the correct output but when I run it it is a byte and I transform to e.g. String before the Transform message connector it remains as a string after the transform message connector too.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:ftp="http://www.mulesoft.org/schema/mule/ftp" xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw" xmlns:sftp="http://www.mulesoft.org/schema/mule/sftp" xmlns:batch="http://www.mulesoft.org/schema/mule/batch" 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/sftp http://www.mulesoft.org/schema/mule/sftp/current/mule-sftp.xsd
http://www.mulesoft.org/schema/mule/batch http://www.mulesoft.org/schema/mule/batch/current/mule-batch.xsd
http://www.mulesoft.org/schema/mule/ee/ftp http://www.mulesoft.org/schema/mule/ee/ftp/current/mule-ftp-ee.xsd
http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.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/ftp http://www.mulesoft.org/schema/mule/ftp/current/mule-ftp.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd">
<http:request-config name="HTTP_Request_Configuration" host="${host}" port="${userprocess.port}" doc:name="HTTP Request Configuration"></http:request-config>
<sftp:connector name="SFTP" validateConnections="true" doc:name="SFTP" pollingFrequency="1000000"/>
<flow name="userexperienceFlow" >
<sftp:inbound-endpoint connector-ref="SFTP" host="localhost" port="2222" path="//input" user="${ftp.user}" password="${ftp.password}" responseTimeout="10000" doc:name="SFTP"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
payload]]></dw:set-payload>
</dw:transform-message>
<logger level="INFO" doc:name="Logger"/>
<sftp:outbound-endpoint exchange-pattern="one-way" host="localhost" port="2222" responseTimeout="10000" doc:name="SFTP" connector-ref="SFTP" password="${ftp.password}" path="//output" user="${ftp.user}" outputPattern="#[message.inboundProperties.originalFilename+'.processed']"/>
</flow>
</mule>
CSV file
UserId,UserStatus
ON1234,active
ON1235,active
Thanks
try to log message as #[message.payloadAs(java.lang.String)] instead of #[payload].
Also add <dw:input-payload mimeType="application/csv" /> line before this <dw:set-payload>
Hope this helps.
<jms:activemq-connector name="jms-connector" brokerURL="${BrokerURL}" disableTemporaryReplyToDestinations="true" maxRedelivery="10" durable="true" specification="1.1"/>
<jms:endpoint connector-ref="jms-connector" name="SyncRequestsQueue" queue="SyncRequestsQueue">
<jms:transaction action="ALWAYS_BEGIN"/>
</jms:endpoint>
<flow name = "RequestsEntryFlow" >
<http:listener allowedMethods="POST" parseRequest="false" config-ref="HTTP_Request_Listener" path="/{name}" doc:name="HTTP Entry Flow" />
<flow-ref name="requestBeanCreate" />
<jms:outbound-endpoint connector-ref="jms-connector" exchange-pattern="request-response" ref="SyncRequestsQueue" />
</flow>
<flow name = "SyncRequestsQueueConsumer">
<jms:inbound-endpoint connector-ref="jms-connector" exchange-pattern="request-response" ref="SyncRequestsQueue" />
<set-variable variableName="id" value="#[payload]" doc:name="Variable" />
<set-variable variableName="destination" value="#[app.registry.routerBean.getDestination(app.registry.messageBean.getReceiverID(payload))]" doc:name="Variable" />
<set-payload value="#[app.registry.messageBean.sendRequestToDestination(payload)]" />
<processor-chain>
<http:outbound-endpoint address="http://#[flowVars.destination]" exchange-pattern="request-response">
<transformer ref="contentTypeTextXML"/>
</http:outbound-endpoint>
<expression-component>
app.registry.messageBean.sendResponseToSender(flowVars.id);
app.registry.messageBean.messageProcessedSuccessfully(flowVars.id);
</expression-component>
</processor-chain>
</flow>
This is the scenario:
A requests to a remote service comes in to RequestsEntryFlow.
I do some logging stuff with it and send it to SyncRequestsQueue.
The SyncRequestsQueueConsumer consumes the queue and sends the content to a remote server.
Now i want to return the response of remote server back to RequestsEntryFlow and from there back to the service Caller.
but the response is not getting back to service caller.
note: when i eliminate JMS and Activemq from the code and use SyncRequestsQueueConsumer as a sub-flow everything works fine. so i guess JMS connectors are not working the way i need them.
What is wrong with the code and how can i solve it? thank you
--EDIT--
I have changed my code to adopt scope and now it looks like this :
<flow name = "RequestsEntryFlow" >
<http:listener allowedMethods="POST" parseRequest="false" config-ref="HTTP_Request_Listener" path="/{name}" doc:name="HTTP Entry Flow" />
<flow-ref name="requestBeanCreate" />
<choice doc:name="Choice">
<when expression="#[app.registry.messageBean.isEMCRequired(payload)]">
<jms:outbound-endpoint connector-ref="jms-connector" ref="EMCRequiredRequestsQueue" />
</when>
<otherwise>
<request-reply>
<jms:outbound-endpoint connector-ref="jms-connector" exchange-pattern="one-way" ref="SyncRequestsQueue" />
<jms:inbound-endpoint connector-ref="jms-connector" exchange-pattern="one-way" queue="ResponseTempQueue" >
<set-payload value="#[payload.get(0)]"/>
<remove-property propertyName="Content_Type"/>
<transformer ref="contentTypeTextXML"/>
</jms:inbound-endpoint>
</request-reply>
</otherwise>
</choice>
</flow>
<flow name = "SyncRequestsQueueConsumer">
<jms:inbound-endpoint connector-ref="jms-connector" exchange-pattern="request-response" ref="SyncRequestsQueue" />
<set-variable variableName="id" value="#[payload]" doc:name="Variable" />
<set-variable variableName="destination" value="#[app.registry.routerBean.getDestination(app.registry.messageBean.getReceiverID(payload))]" doc:name="Variable" />
<set-payload value="#[app.registry.messageBean.sendRequestToDestination(payload)]" />
<http:outbound-endpoint address="http://#[flowVars.destination]" exchange-pattern="request-response">
<transformer ref="contentTypeTextXML"/>
</http:outbound-endpoint>
<expression-component>
app.registry.messageBean.sendResponseToSender(flowVars.id);
app.registry.messageBean.messageProcessedSuccessfully(flowVars.id);
</expression-component>
</flow>
If i add e logger to my code it will print the proper payload (the response from server)
<jms:inbound-endpoint connector-ref="jms-connector" exchange-pattern="one-way" queue="ResponseTempQueue" >
<set-payload value="#[payload.get(0)]"/>
<remove-property propertyName="Content_Type"/>
<transformer ref="contentTypeTextXML"/>
<logger level="INFO" message="#[payload]" />
</jms:inbound-endpoint>
but the response is not routing back to sender through HTTP
try with request-reply scope in RequestsEntryFlow
in request reply scope in the request block define your SyncRequestsQueue and a VM in reply block of request-reply scope.
in SyncRequestsQueueConsumer flow at the end of flow define the VM with same queue name as defined in reply block of request-reply scope.
I guess you are not using the request-reply correctly. Can you please go through sample implementation of request-reply scope and understand the request-reply scope.
I hope this this helps to some extent:
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="raml-http-request-connectorFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" doc:name="HTTP"/>
<set-payload value="heloo" doc:name="Set Payload"/>
<request-reply doc:name="Request-Reply">
<vm:outbound-endpoint exchange-pattern="one-way" path="input" doc:name="VM"/>
<vm:inbound-endpoint exchange-pattern="one-way" path="output" doc:name="VM"/>
</request-reply>
<logger message="log payload is:::::::::::::::::::::#[payload]" level="INFO" doc:name="Logger"/>
</flow>
<flow name="raml-http-request-connectorFlow1">
<vm:inbound-endpoint exchange-pattern="one-way" path="input" doc:name="VM"/>
<set-payload value="#[payload+' welome']" doc:name="Set Payload"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="output" doc:name="VM"/>
</flow>
i am trying to integrate mule with drools, i have mainly followed the tutorial here but i am getting this error :
(1,22) unqualified type in strict mode for: MessageExchangePattern
(1,30) unqualified type in strict mode for: ONE_WAY '
it seems impossible to find the solution to me, can any one help me? thanks.
this is my .drl file :
global org.mule.module.bpm.MessageService mule;
import com.hamgam.hit.esb.*;
rule "La Vita Ebela"
dialect "mvel"
when
$x:XMLDTO( inputXML == "inputXML" )
then
mule.generateMessage("emc", "KeyValueMatched", null, MessageExchangePattern.ONE_WAY);
end
and this is mules flow :
<?xml version="1.0" encoding="UTF-8"?>
<mule
xmlns:bpm="http://www.mulesoft.org/schema/mule/bpm"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" 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" version="EE-3.6.0"
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/http http://www.mulesoft.org/schema/mule/http/current/mule-http.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/bpm http://www.mulesoft.org/schema/mule/bpm/3.6/mule-bpm.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/3.6/mule-vm.xsd ">
<http:listener-config name="HTTP_Listener_Configuration"
host="localhost" port="8084" doc:name="HTTP Listener Configuration" />
<spring:beans>
<spring:bean id="dto" class="com.hamgam.hit.esb.XMLDTO" scope="singleton" />
<spring:bean id="dto-convertor" class="com.hamgam.hit.esb.XMLToDTO" scope="singleton" />
<spring:bean id="rule-convertor" class="com.hamgam.hit.esb.RuleXMLToDRL" scope="singleton" />
</spring:beans>
<bpm:drools />
<flow name="basic_tutorialFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/{name}" doc:name="HTTP" />
<vm:endpoint name = "emc" path="drool.msg" />
<set-variable variableName="name" value="#[message.inboundProperties['http.uri.params']['name']]" />
<set-variable variableName="msg" value="#[payload]"/>
<logger level="DEBUG" doc:name="Logger" message="Current path is flowVars['name']" />
<expression-component>
app.registry['dto'] = app.registry['dto-convertor'].convert(flowVars['name']);
</expression-component>
<bpm:rules rulesDefinition="rule.drl" cepMode="true" initialFacts-ref="dto" entryPoint="XMLDTO stream" />
<choice doc:name="Choice">
<when expression="#[flowVars.emc == 'KeyValueMatched']">
<set-payload doc:name="Set Payload" value="#['KeyValueMatched! You are with us on 8084. ' + flowVars['name'] + '. Today is ' + server.dateTime.format('dd/MM/yy') + '.' ]" />
</when>
<otherwise>
<set-payload doc:name="Set Payload" value="#['Nothing! You are with us on 8084. ' + flowVars['name'] + '. Today is ' + server.dateTime.format('dd/MM/yy') + '.' ]" />
</otherwise>
</choice>
</flow>
</mule>
You need to:
import org.mule.MessageExchangePattern
Otherwise your Drools MVEL script will have no idea what MessageExchangePattern.ONE_WAY is.
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.
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.