In trying to restore the original payload in a message, I ran into this issue that confused me regarding the scope of a mule message. Given the mule config below, I initially assumed that the payload received at the test.Name vm endpoint was going to be restored at the end of the flow (see 1. and 2. in the config):
<mule ...>
<vm:endpoint name="replacePayloadWithFoo.Name"
path="replacePayloadWithFoo.Path" />
<flow name="test">
<vm:inbound-endpoint name="test.Name" path="test.Path"
exchange-pattern="request-response" />
<!-- 1. Down below, I wanted to restore the payload at this point -->
<expression-transformer evaluator="string"
expression="bar" />
<outbound-endpoint ref="replacePayloadWithFoo.Name"
exchange-pattern="request-response" />
<!-- 2. The transformer below does not restore the payload at 1. -->
<expression-transformer evaluator="groovy"
expression="message.originalPayload" />
</flow>
<flow name="replacePayloadWithFoo">
<inbound-endpoint ref="replacePayloadWithFoo.Name"
exchange-pattern="request-response" />
<expression-transformer evaluator="string"
expression="foo" />
</flow>
</mule>
However, it seemed as though the message that entered the test flow ended at the replacePayloadWithFoo outbound endpoint. The transformer at 2. leaves "foo" as the payload.
What's the scope of the mule message?
In passing, the scripting reference documentation indicates that there is a binding for originalPayload in groovy scripts. However, if the transformer at 2. is replaced with
<expression-transformer evaluator="groovy" expression="originalPayload" />
I get an exception:
org.mule.api.expression.RequiredValueException: Expression Evaluator "groovy"
with expression "originalPayload" returned null but a value was required.
What could be the issue?
Thanks
Any outbound interaction, unless performed through an enricher, will affect the current in-flight message. This is why the call to replacePayloadWithFoo replaces the original message with the result of the outbound interaction.
This said, I can not explain the discrepancy between:
<expression-transformer evaluator="groovy" expression="message.originalPayload" />
and:
<expression-transformer evaluator="groovy" expression="originalPayload" />
because they both rely on:
event.getMessage().getPayload()
Related
I am facing problem in batch processing mule esb. If I set any payload in process record face and try to get that payload in oncomplete face then not getting that payload. same problem with variable and property.
If I set any property in process record phase and try to get in on complete phase then always get null value.
how to get those value in oncomplete phase?
below is flow..
<batch:job name="TestBatch" max-failed-records="-1">
<batch:input>
<component class="com.test.RecordTest"
doc:name="Java" />
<json:object-to-json-transformer
doc:name="Object to JSON" />
<custom-transformer class="com.test.CustomTr"
doc:name="Java" />
</batch:input>
<batch:process-records>
<batch:step name="Batch_Step1" accept-policy="ALL">
<batch:commit size="5" doc:name="Batch Commit">
<!-- Insert record in Salesforce -->
</batch:commit>
</batch:step>
<batch:step name="Batch_Step2" accept-policy="ONLY_FAILURES">
<logger message="STEPP #[getStepExceptions()]" level="INFO" doc:name="Logger"/>
<set-property propertyName="error" value="STEPP #[getStepExceptions()]" doc:name="Property"/>
<set-payload value="#[getStepExceptions()]" doc:name="Set Payload"/>
</batch:step>
</batch:process-records>
<batch:on-complete>
<logger level="INFO" doc:name="Logger" message="--> #[payload.failedRecords] --> #[message.payload] "/>
<logger message="error--- #[message.outboundProperties['error']] " level="INFO" doc:name="Logger"/>
</batch:on-complete>
</batch:job>
I got null in property logger
How can I solve this?
I got some bad news from you :-).
Batch processing by design will not old any of the value you may try to set in steps, especially payload.
When I started working with it I was also expecting to have session variable on complete phase in a correct status but this is not the case, they are completely wiped at each step.
Now I don't think this is a bug, but it is really a design feature that I can understend even if I don't really love it.
I solved the same problem by using the object store connector.
It will allow you to access the mule Object Store API via nice XML configuration block, in this way you can store in memory variables that you can recover after in your on-complete without them being affected by flow logic.
Hope this helps
This has to be a common scenario yet I only came across the following link so far addressing it - I have a bunch of Data Mapper elements doing Pojo to Pojo transformation and need a way to reliably capture the exceptions - right now an exception happens but there is no indication of which mapper the exception occurred in.
http://www.mulesoft.org/documentation/display/current/DataMapper+Input+Error+Policy+for+Bad+Input+Data
Can someone please point to a link which describes how to capture these errors in the mapper
Thanks
The easiest way is probably to put each data mapper transformer in a private flow with their own local exception strategies:
<flow name="main">
<flow-ref name="transform1" />
<flow-ref name="transform2" />
</flow>
<flow name="transform1">
<data-mapper:transform config-ref="grf1" />
<catch-exception-strategy>
<!-- do something -->
</catch-exception-strategy>
</flow>
<flow name="transform2">
<data-mapper:transform config-ref="grf2" />
<catch-exception-strategy>
<!-- do something -->
</catch-exception-strategy>
</flow>
I have 2 flows, A.flow and B.flow, eventually both flows execute the same java class.
A & B read from a separate Queue.
I want to synchronize the flows so that if both flows get input simultaneously then one flow at a time process and after it finishes, the other flow will start processing.
Any ideas?
thanks
Use a pooled component and configure it to use one thread at a time:
<flow name="A">
<jms:inbound-endpoint...>
...
<vm:outbound-endpoint path="process"/>
...
</flow>
<flow name="B">
<jms:inbound-endpoint...>
...
<vm:outbound-endpoint path="process"/>
...
</flow>
<flow name="process">
<vm:inbound-endpoint path="process"/>
<pooled-component class="org.my.PrototypeObject">
<pooling-profile exhaustedAction="WHEN_EXHAUSTED_WAIT" initialisationPolicy="INITIALISE_ALL" maxActive="1" maxIdle="1" maxWait="1000" /> </pooled-component>
</pooled-component>
</flow>
Source: http://www.mulesoft.org/documentation/display/current/Configuring+Java+Components#ConfiguringJavaComponents-ConfiguringaPooledJavaComponent
I have a flow in which I have inserted a flow reference component. The reference component flow will obviously send a message to my first flow with a result "xxx". I want this result to be put in the header of the message sent.
<flow name="CreateAccountFlow1" doc:name="CreateAccountFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP" path="bank"/>
<cxf:jaxws-service doc:name="SOAP" serviceClass="com.essai2.AccountService"/>
<component class="com.essai2.AccountRequest" doc:name="Java"/>
<flow-ref name="Projet2Flow1" doc:name="Flow Reference"/>
<component class="com.essai2.AccountResponse" doc:name="Java"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
Flow-references do not "send messages" per se, so it's hard to understand what you're after. It seems you want the result of the execution of the flow-ref to be placed in a message property. If that's the case, you can do:
<set-variable variableName="result" value="#[message.payload]" />
This assumes that the result of the flow-ref is in the message payload and that having the result property in the invocation scope (aka flow variable) is OK for you. With the little information you provided, that's the most I can tell you.
<flow>
<jms:inbound-endpoint queue="InputQueue"/>
<component class="MyComponent"/>
<choice>
<when expression="/Response/Status/Success" evaluator="xpath">
<jms:outbound-endpoint queue="LogInputQueue"/>
<jms:outbound-endpoint queue="SuccessQueue"/>
</when>
<when expression="/Response/Status/Error" evaluator="xpath">
<jms:outbound-endpoint queue="LogInputQueue"/>
<jms:outbound-endpoint queue="ErrorQueue"/>
</when>
<otherwise>
<jms:outbound-endpoint queue="LogInputQueue"/>
<jms:outbound-endpoint queue="ExceptionQueue"/>
</otherwise>
</choice>
</flow>
In this flow, MyComponent returns either success message as a response or error response or exception?
I need to log the original message from InputQueue in LogInputQueue in all the cases. How do I achieve this in my flow?
Did you mean to create a log file? In that case, you have to implement log4j using slf4j and use the line
<logger level="log_level" category="your_category" message="#[message:payload]"/>
where log_level is your desired logging level- "error", "debug", "info" etc...
your_category is your category of log defined in the log4j.properties file (it is optional actually)
and message="#[expression:value]" is your message to be logged given as an expression:scope:key combination. Scope is optional here.
Using log4j or slf4j you can log the payload.
[payload],we have logger component using this log payload in console.
Since, you need to send original message from InputQueue to LogInputQueue in all the cases, as you mentioned, what you need to do is :-
1. Remove <jms:outbound-endpoint queue="LogInputQueue"/> from all the cases in choice block
2. Store the original payload from InputQueue in a variable by placing it just after the JMS inbound endpoint
3. At the end of the flow, after the choice router, set the payload in set payload component from variable you stored the original payload
4. Now put <jms:outbound-endpoint queue="LogInputQueue"/> after your set payload component.
In this way you will able to send the original payload to the LogInputQueue as per your requirement.