In Mule flow how can I re-use choice-exception-stretegy across several flows?
I tried the following, but it throws error when I run mule application.
<mule ....>
<choice-exception-strategy doc:name="My_exception_strategy">
<catch-exception-strategy when="exception.causedBy(java.net.SocketTimeoutException)" doc:name="Strategy1">
<logger message="message 1" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
<catch-exception-strategy when="exception.causedBy(java.lang.Throwable)" doc:name="Strategy2">
<logger message="message 2" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
<flow name="Test1" doc:name="Test1" processingStrategy="synchronous">
<logger message="message 3" level="INFO" doc:name="Logger"/>
<outbound-endpoint ref="myendpoint" doc:name="MyEndPoint"/>
<exception-strategy ref="My_exception_strategy" doc:name="Reference Exception Strategy"/>
<set-variable variableName="somevalue" value="#[something]" doc:name="statusCode"/>
</flow>
</mule>
There are two issues with the config you have posted.
There is a "set-variable" after the exception strategy. No other processors are expected after the "exception-strategy".
The exception strategy is not named. The attribute "name" is missing for the exception strategy.
Try the following flow .
<mule ....>
<choice-exception-strategy name="my_exception_strategy" doc:name="My_exception_strategy">
<catch-exception-strategy when="exception.causedBy(java.net.SocketTimeoutException)" doc:name="Strategy1">
<logger message="message 1" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
<catch-exception-strategy when="exception.causedBy(java.lang.Throwable)" doc:name="Strategy2">
<logger message="message 2" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
<flow name="Test1" doc:name="Test1" processingStrategy="synchronous">
<logger message="message 3" level="INFO" doc:name="Logger"/>
<outbound-endpoint ref="myendpoint" doc:name="MyEndPoint"/>
<exception-strategy ref="my_exception_strategy" doc:name="Reference Exception Strategy"/>
</flow>
</mule>
Hope this helps.
Related
The problem statement is to do multiple things parallely and aggregate the response and store it in a file.
link to the mule flow image as in studio:
image
In this flow, what I was trying to do was to set two constant strings in two branches of scatter and gather and aggregate and store in file. I tried overwriting the payload with a "set payload" with "my response". I am expecting "my response" as the content of the file. But instead the file content is:
¨Ìsr)java.util.concurrent.CopyOnWriteArrayListx]ü’F´ê√xpwtmsg 1tmsg 2x
I did debug and the payload at File endpoint was "my response". How and why is the collection getting written into file.
Can anyone help me to get it working.
Following is the xml:
<flow name="mule-assignFlow21123">
<quartz:inbound-endpoint jobName="dummyflow" repeatInterval="10000" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job/>
</quartz:inbound-endpoint>
<scatter-gather doc:name="Scatter-Gather1" >
<threading-profile maxThreadsActive="1" poolExhaustedAction="RUN"/>
<processor-chain>
<set-payload value="msg 1" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
</processor-chain>
<processor-chain>
<set-payload value="msg 2" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
</processor-chain>
</scatter-gather>
<set-payload value="my response" doc:name="Set Payload"/>
<file:outbound-endpoint path="/Users/premkumar/Desktop" outputPattern="Results.txt" responseTimeout="10000" mimeType="text/plain" doc:name="Save 2 File"/>
</flow>
The flow will automatically determine the processingStrategy from the in-flight event which will be async because of the quartz endpoint, so the file endpoint will fire async also.
Instead explicitly set the flow's processingStrategy to synchronous:
<flow name="mule-assignFlow21123" processingStrategy="synchronous">
<quartz:inbound-endpoint jobName="dummyflow" repeatInterval="10000" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job/>
</quartz:inbound-endpoint>
<scatter-gather doc:name="Scatter-Gather1" >
<threading-profile maxThreadsActive="1" poolExhaustedAction="RUN"/>
<processor-chain>
<set-payload value="msg 1" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
</processor-chain>
<processor-chain>
<set-payload value="msg 2" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
</processor-chain>
</scatter-gather>
<set-payload value="my response" doc:name="Set Payload"/>
<file:outbound-endpoint path="/Users/premkumar/Desktop" outputPattern="Results.txt" responseTimeout="10000" mimeType="text/plain" doc:name="Save 2 File"/>
I've a mule flow where I configured Request Reply scope. The flow is like below:
<flow name="RequestReplyFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" doc:name="HTTP" />
<set-payload value="#['Sample Payload']" doc:name="Set Payload" />
<request-reply doc:name="Request-Reply">
<vm:outbound-endpoint exchange-pattern="one-way" path="request" doc:name="VM" />
<vm:inbound-endpoint exchange-pattern="one-way" path="reply" doc:name="VM" />
</request-reply>
</flow>
and
<flow name="RequestReplyFlow1">
<vm:inbound-endpoint exchange-pattern="one-way" path="request" doc:name="VM" />
<logger message="Executing with payload: #[payload]" level="INFO" doc:name="Logger" />
<component class="org.ram.BusinessComponent" doc:name="Java" />
<rollback-exception-strategy maxRedeliveryAttempts="5" doc:name="Rollback Exception Strategy">
<logger message="Will attempt redelivery" level="INFO" doc:name="Logger" />
</rollback-exception-strategy>
</flow>
I configure rollback-exception-strategy on the request VM inbound endpoint.
When the component org.ram.BusinessComponent throws an exception, what I expected is the message is redelivered to the inbound VM endpoint but it did not happen. Why?
Can anyone please solve the issue?
If you are using rollback exception strategy instead of default exception strategy for unhandled exceptions, then you just have to specify the redirection manually in the "rollback-exception-strategy" by adding the "vm:outbound-endpoint" with the "reply" path, note that the maxRedeliveryAttempts was changed to "0" because your vm is not transactional:
<flow name="RequestReplyFlow1">
<vm:inbound-endpoint exchange-pattern="one-way" path="request" doc:name="VM" />
<logger message="Executing with payload: #[payload]" level="INFO" doc:name="Logger" />
<component class="org.ram.BusinessComponent" doc:name="Java" />
<rollback-exception-strategy maxRedeliveryAttempts="0" doc:name="Rollback Exception Strategy">
<logger message="Will attempt redelivery" level="INFO" doc:name="Logger" />
<vm:outbound-endpoint exchange-pattern="one-way" path="reply" doc:name="VM" />
</rollback-exception-strategy>
</flow>
When the vm is transactional then the value maxRedeliveryAttempts=5 makes sense because in that case Mule attempts message redelivery five (5) times. Then you can specify the redirection manually in the "rollback-exception-strategy" by adding the "vm:outbound-endpoint" with the "reply" path inside the "on-redelivery-attempts-exceeded" child element:
<flow name="RequestReplyFlow1">
<vm:inbound-endpoint exchange-pattern="one-way" path="request" doc:name="VM" />
<logger message="Executing with payload: #[payload]" level="INFO" doc:name="Logger" />
<component class="org.ram.BusinessComponent" doc:name="Java" />
<rollback-exception-strategy maxRedeliveryAttempts="0" doc:name="Rollback Exception Strategy">
<logger message="Will attempt redelivery" level="INFO" doc:name="Logger" />
<on-redelivery-attempts-exceeded>
<logger message="redelivery attempt exceeded" level="INFO" doc:name="Logger" />
<vm:outbound-endpoint exchange-pattern="one-way" path="reply" doc:name="VM" />
</on-redelivery-attempts-exceeded>
</rollback-exception-strategy>
</flow>
I am iterating xml in foreach. Echo is printing correct message but logger is print null.
<foreach collection="#[xpath('//xmlsoap/soap/soapenv:Envelope')]"
doc:name="For Each">
<echo-component />
<logger level="INFO" category="ProTSP Logger" message="#[payload]"
doc:name="Logger" />
</foreach>
I resolved my problem using dom to xml transformer.
<foreach collection="#[xpath('//xmlsoap/soap/soapenv:Envelope')]"
doc:name="For Each">
<echo-component doc:name="Echo"/>
<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
<logger level="INFO" category="ProTSP Logger" message="#[payload]"
doc:name="Logger" />
</foreach>
I was exploring Mule scatter-gather for parallel processing of flows in Mule fork and join pattern. My Mule config is as follows:
<flow name="fork" doc:name="fork">
<http:inbound-endpoint host="localhost" port="8090" path="mainPath" exchange-pattern="request-response" doc:name="HTTP"/>
<set-property propertyName="MULE_CORRELATION_GROUP_SIZE" value="2" doc:name="Property"/>
<!-- <all enableCorrelation="IF_NOT_SET" doc:name="All"> -->
<scatter-gather timeout="6000">
<processor-chain>
<async doc:name="Async">
<set-property propertyName="MULE_CORRELATION_SEQUENCE" value="1" doc:name="Property"/>
<flow-ref name="Flow1" doc:name="Flow Reference"/>
</async>
</processor-chain>
<async doc:name="Async">
<set-property propertyName="MULE_CORRELATION_SEQUENCE" value="2" doc:name="Property"/>
<flow-ref name="Flow2" doc:name="Flow Reference"/>
</async>
<!-- </all> -->
</scatter-gather>
<logger message="Main Flow" level="INFO" doc:name="Logger"/>
</flow>
<sub-flow name="Flow1" doc:name="Flow1">
<logger level="INFO" message="Flow1: processing started" doc:name="Logger"/>
<set-payload value="Flow1 Payload" doc:name="Set Payload"/>
<!-- Transformation payload -->
<logger level="INFO" message="Flow1: processing finished" doc:name="Logger"/>
<flow-ref name="Join-Flow" doc:name="Flow Reference"/>
</sub-flow>
<sub-flow name="Flow2" doc:name="Flow2">
<logger level="INFO" message="Flow2: processing started" doc:name="Logger"/>
<set-payload value="Flow2 Payload" doc:name="Set Payload"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[sleep(2000); return message.payload;]]></scripting:script>
</scripting:component>
<!-- Transformation payload -->
<logger level="INFO" message="Flow2: processing finished" doc:name="Logger"/>
<flow-ref name="Join-Flow" doc:name="Flow Reference"/>
</sub-flow>
<sub-flow name="Join-Flow" doc:name="Join-Flow">
<collection-aggregator timeout="6000" failOnTimeout="true" doc:name="Collection Aggregator"/>
<combine-collections-transformer doc:name="Combine Collections"/>
<logger level="INFO" message="Combined Payload: #[message.payload]" doc:name="Logger"/>
<set-payload value="Soap XML Response" doc:name="Set Payload"/>
</sub-flow>
The scatter and gather is throwing following exception though I am getting the aggregated Payload in Logger:
Exception stack is:
1. null (java.lang.UnsupportedOperationException)
org.mule.VoidMuleEvent:50 (null)
2. null (java.lang.UnsupportedOperationException). Message payload is of type: String (org.mule.api.MessagingException)
org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor:32 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
java.lang.UnsupportedOperationException
at org.mule.VoidMuleEvent.getMessage(VoidMuleEvent.java:50)
at org.mule.api.routing.AggregationContext$1.evaluate(AggregationContext.java:41)
at org.apache.commons.collections.CollectionUtils.select(CollectionUtils.java:517)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
INFO 2014-08-17 18:04:52,008 [[try1].fork.2.02] org.mule.api.processor.LoggerMessageProcessor: Flow2: processing started
INFO 2014-08-17 18:04:52,016 [[try1].fork.1.02] org.mule.api.processor.LoggerMessageProcessor: Flow1: processing started
INFO 2014-08-17 18:04:52,017 [[try1].fork.1.02] org.mule.api.processor.LoggerMessageProcessor: Flow1: processing finished
INFO 2014-08-17 18:04:54,309 [[try1].fork.2.02] org.mule.api.processor.LoggerMessageProcessor: Flow2: processing finished
INFO 2014-08-17 18:04:54,347 [[try1].fork.2.02] org.mule.api.processor.LoggerMessageProcessor: Combined Payload: [Flow1 Payload, Flow2 Payload]
One interesting fact is that if I use <all> router instead of scatter-gather, I don't get this exception. but I guess <all> router process the flows sequentially and not in parallel as per Mule documentation. So for that reason I tried to choose scatter-gather over all router. But I am not sure how to handle the above exception thrown by the scatter-gather. Is there any way out?
UPDATED FLOW :-
<flow name="fork" doc:name="fork">
<http:inbound-endpoint host="localhost" port="8090" path="mainPath" exchange-pattern="request-response" doc:name="HTTP"/>
<scatter-gather timeout="6000">
<processor-chain>
<flow-ref name="Flow1" doc:name="Flow Reference"/>
</processor-chain>
<flow-ref name="Flow2" doc:name="Flow Reference"/>
</scatter-gather>
<logger message="Main Flow" level="INFO" doc:name="Logger"/>
</flow>
<sub-flow name="Flow1" doc:name="Flow1">
<logger level="INFO" message="Flow1: processing started" doc:name="Logger"/>
<set-payload value="Flow1 Payload" doc:name="Set Payload"/>
<!-- Transformation payload -->
<logger level="INFO" message="Flow1: processing finished" doc:name="Logger"/>
<flow-ref name="Join-Flow" doc:name="Flow Reference"/>
</sub-flow>
<sub-flow name="Flow2" doc:name="Flow2">
<logger level="INFO" message="Flow2: processing started" doc:name="Logger"/>
<set-payload value="Flow2 Payload" doc:name="Set Payload"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[sleep(2000); return message.payload;]]>
</scripting:script>
</scripting:component>
<!-- Transformation payload -->
<logger level="INFO" message="Flow2: processing finished" doc:name="Logger"/>
<flow-ref name="Join-Flow" doc:name="Flow Reference"/>
</sub-flow>
<sub-flow name="Join-Flow" doc:name="Join-Flow">
<collection-aggregator timeout="6000" failOnTimeout="true" doc:name="Collection Aggregator"/>
<combine-collections-transformer doc:name="Combine Collections"/>
<logger level="INFO" message="Combined Payload: #[message.payload]" doc:name="Logger"/>
<set-payload value="Soap XML Response" doc:name="Set Payload"/>
</sub-flow>
EXCEPTION :-
[try1].ScatterGatherWorkManager.02] org.mule.api.processor.LoggerMessageProcessor: Flow2: processing started
INFO 2014-08-18 13:34:24,361 [[try1].ScatterGatherWorkManager.01] org.mule.api.processor.LoggerMessageProcessor: Flow1: processing started
INFO 2014-08-18 13:34:24,364 [[try1].ScatterGatherWorkManager.01] org.mule.api.processor.LoggerMessageProcessor: Flow1: processing finished
WARN 2014-08-18 13:34:24,366 [[try1].ScatterGatherWorkManager.01] org.mule.routing.correlation.CollectionCorrelatorCallback: Correlation Group Size not set, but correlation aggregator is being used. Message is being forwarded as is
INFO 2014-08-18 13:34:24,401 [[try1].ScatterGatherWorkManager.01] org.mule.api.processor.LoggerMessageProcessor: Combined Payload: [Flow1 Payload]
INFO 2014-08-18 13:34:26,615 [[try1].ScatterGatherWorkManager.02] org.mule.api.processor.LoggerMessageProcessor: Flow2: processing finished
ERROR 2014-08-18 13:34:26,625 [[try1].connector.http.mule.default.receiver.03] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : null (java.lang.NullPointerException). Message payload is of type: String
Code : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. null (java.lang.NullPointerException)
org.mule.api.routing.AggregationContext$1:41 (null)
2. null (java.lang.NullPointerException). Message payload is of type: String (org.mule.api.MessagingException)
org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor:32 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
java.lang.NullPointerException
at org.mule.api.routing.AggregationContext$1.evaluate(AggregationContext.java:41)
at org.apache.commons.collections.CollectionUtils.select(CollectionUtils.java:517)
at org.apache.commons.collections.CollectionUtils.select(CollectionUtils.java:498)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
Now as you can see it's not combining the both payload of both flow after removing the set-property ..... It is getting only payload of first flow :- Combined Payload: [Flow1 Payload] ..
Remove the async scope around the message processors in the scatter-gather, which indeed does the parallelization for you so you don't have to.
EDIT: Also remove the set-property message processors that deal with the MULE_CORRELATION properties. The scatter-gather is supposed to do that for you.
EDIT2: You can remove the processor-chain around the single flow-ref: it's useless.
Also, there seem to be a deep misunderstanding about what scatter-gather does: you forcefully make its sub-flow responses converge to a single Join-Flow where you aggregate stuff, effectively by-passing and re-implementing all what the scatter-gather proposes to do for you.
Remove the flow-refs towards Join-Flow, remove Join-Flow and just put its processing logic (not the aggregator) after the scatter-gather.
So as per David's suggestion the final working solution is :-
<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 Flow1 -->
<flow-ref name="Flow1" doc:name="Flow Reference"/>
<!-- Calling Flow2 -->
<flow-ref name="Flow2" doc:name="Flow Reference"/>
</scatter-gather>
<!-- <collection-aggregator timeout="6000" failOnTimeout="true" doc:name="Collection Aggregator"/>
<combine-collections-transformer doc:name="Combine Collections"/> -->
<logger level="INFO" message="Combined Payload: #[message.payload]" doc:name="Logger"/>
<logger level="INFO" message="Payload1: #[message.payload[0]] and Payload2: #[message.payload[1]] " doc:name="Logger"/>
<set-payload value="Done Merging ...!!!" doc:name="Set Payload"/>
<logger message="Back to Main Flow" level="INFO" doc:name="Logger"/>
</flow>
<sub-flow name="Flow1" doc:name="Flow1">
<logger level="INFO" message="Flow1: processing started" doc:name="Logger"/>
<set-payload value="Flow1 Payload" doc:name="Set Payload"/>
<logger level="INFO" message="Flow1: processing finished" doc:name="Logger"/>
</sub-flow>
<sub-flow name="Flow2" doc:name="Flow2">
<logger level="INFO" message="Flow2: processing started" doc:name="Logger"/>
<!-- Sleep function to delay the flow2 payload -->
<set-payload value="Flow2 Payload" doc:name="Set Payload"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[sleep(3000); return message.payload;]]></scripting:script>
</scripting:component>
<logger level="INFO" message="Flow2: processing finished" doc:name="Logger"/>
</sub-flow>
</mule>
I am using the following fork and join pattern in my flow.Parallel processing works just fine. However, I have issues with exception handling. I want to implement an exception strategy for the processing happening on VM response inbound endpoint of the router. However, it seems my nothing happens when I am trying to write to response, from within the catch exception strategy block. When there is an exception, I am able to see the log statement from the catch block, but the response on browser just hangs.
Please suggest.
<flow name="forkAndJoinFlow" doc:name="forkAndJoinFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="81" path="lowestprice" doc:name="HTTP"/>
<not-filter doc:name="Not">
<wildcard-filter pattern="*favicon*" caseSensitive="true"/>
</not-filter>
<request-reply>
<all>
<vm:outbound-endpoint path="shop1"/>
<vm:outbound-endpoint path="shop2"/>
</all>
<vm:inbound-endpoint path="response">
<message-properties-transformer>
<add-message-property key="MULE_CORRELATION_GROUP_SIZE" value="2" />
</message-properties-transformer>
<collection-aggregator />
</vm:inbound-endpoint>
</request-reply>
<expression-transformer evaluator="groovy" expression="java.util.Collections.min(payload)" doc:name="Expression"/>
<object-to-string-transformer doc:name="Object to String"/>
<logger level="WARN" message="#[string:Lowest price: #[payload]]" doc:name="Logger"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="EXCEPTION:#[payload]" level="INFO" doc:name="Logger"></logger>
<!--Nothing happens after this-->
<object-to-string-transformer doc:name="Object to String"></object-to-string-transformer></catch-exception-strategy>
</flow>
<flow name="shop1Flow" doc:name="shop1Flow">
<vm:inbound-endpoint path="shop1" doc:name="VM"/>
<logger level="INFO" message="SHOP1 Flow..." doc:name="Logger"/>
<expression-transformer evaluator="groovy" expression="new java.lang.Double(1000.0 * Math.random()).intValue()" doc:name="Expression"/>
<logger level="WARN" message="#[string:Price from shop 1: #[payload]]" doc:name="Logger"/>
</flow>
<flow name="shop2Flow" doc:name="shop2Flow">
<vm:inbound-endpoint path="shop2" doc:name="VM"/>
<logger level="INFO" message="SHOP2 Flow..." doc:name="Logger"/>
<expression-transformer evaluator="groovy" expression="new java.lang.Double(1000.0 * Math.random()).intValue()" doc:name="Expression"/>
<logger level="WARN" message="#[string:Price from shop 2: #[payload]]" doc:name="Logger"/>`enter code here`
</flow>
</mule>