Below is a exception strategy part of the flow
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="exception.causedBy(java.sql.BatchUpdateException)" doc:name="SQL deadlock error">
<logger message="SQL EXCEPTION - RETRYING BATCH PROCESS"
level="ERROR" doc:name="Payload Logger" category="asi_user"/>
<set-variable variableName="Exception" value="User" doc:name="Exception Type"/>
<flow-ref name="Reload_Batch" doc:name="Retry Batch Results"/>
</catch-exception-strategy>
<catch-exception-strategy when="exception.causedBy(com.microsoft.sqlserver.jdbc.SQLServerException)" doc:name="SQL error">
<logger message="SQL EXCEPTION - RETRYING BATCH PROCESS"
level="ERROR" category="asi_user" doc:name="Payload Logger" />
<set-variable variableName="Exception" value="User" doc:name="Exception Type"/>
<flow-ref name="Reload_Batch" doc:name="Retry Batch Results"/>
</catch-exception-strategy>
<catch-exception-strategy doc:name="Unexpected errors">
<logger message="UNEXPECTED EXCEPTION - SEND EMAIL NOTIFICATION"
level="ERROR" category="asi_user" doc:name="Payload Logger" />
<set-payload value="#[exception.cause.message]" doc:name="Set Payload"/>
<flow-ref name="Send_Error_Notification" doc:name="Send Email Notification"/>
</catch-exception-strategy>
</choice-exception-strategy>
Even when a java.sql.BatchUpdateException is thrown from the flow, the control goes to the final exception strategy "Unexpected Errors", it doesn't go to SQL deadlock error
Am I missing anything to make it work.
Could any please help me with this to make it work.I'm using is Mule server 3.4.0 EE
Thank you in advance
It is the problem with your expression in the when
Try it the following way.
<catch-exception-strategy when="#[exception.causedBy(java.sql.BatchUpdateException)]" doc:name="SQL deadlock error">
Hope this helps.
Related
Is there a connector to stop the Mulesoft flow after a certain point? Let's say I have a request connector in the flow and I want to stop the flow soon after that connector is executed
If its with regards Mule4,
-- https://help.mulesoft.com/s/article/How-To-Stop-Or-Start-Flows-In-Mule-4-x-Programmatically
If its with regards Mule3,
-- https://help.mulesoft.com/s/article/How-to-start-stop-a-flow-programmatically
Alternatively you can try, wherever you want to stop your flow, give a "Raise Error" connector and give the Type as "ANY" and in the error handling section give an empty "on-error-continue" scope and in the on error continue properties uncheck "Log Exception" so that it doesn't log the error we raised.
Please find the below code:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="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:listener-config name="HTTP_Listener_config" doc:name="HTTP Listener config" doc:id="d2c12e71-9f33-44f5-8515-616b1733d52a" >
<http:listener-connection host="0.0.0.0" port="8081" />
</http:listener-config>
<flow name="stop-flow-wsFlow" doc:id="c668e851-46ec-459d-9252-109ec488c47e" >
<http:listener doc:name="Listener" doc:id="e8e5a81d-97f7-4cda-8984-483ead08d376" config-ref="HTTP_Listener_config" path="/stopflow"/>
<logger level="INFO" doc:name="Logger1" doc:id="b1e57888-acf6-41bb-af46-abc54acb8c5b" message='#["Logger1"]'/>
<logger level="INFO" doc:name="Logger2" doc:id="02ba5ce3-69eb-4a8e-ae7a-063cd372ffa9" message='#["Logger2"]'/>
<raise-error doc:name="Raise error" doc:id="872e5b03-64d4-499f-a77c-b69d12bfaf0c" type="ANY"/>
<logger level="INFO" doc:name="Logger3" doc:id="b54480ea-b89b-4b66-b2bd-152617860c4f" message='#["Logger3"]'/>
<set-payload value='#["Hello World"]' doc:name="Set Payload" doc:id="04738f06-77d0-4953-a976-c14589718692" />
<error-handler>
<on-error-continue enableNotifications="true" logException="false" doc:name="On Error Continue" doc:id="87ac9f65-3456-4c00-b76c-c461acf0628c" />
</error-handler>
</flow>
</mule>
Output would be:
How do exception can be rethrow from catch-exception-strategy in mule.
Tried with below flows and after an exception from "flowdemo" errorhandling, it doesn't go to errorhandling of mdemoflow. it executes logger that is place after flow-ref.
<mule ....>
<sub-flow name="exceFlow">
<logger level="ERROR" doc:name="Logger"/>
<expression-component doc:name="Expression"><![CDATA[throw new java.lang.IllegalArgumentException('bad arg');]]></expression-component>
<validation:is-true expression="false" doc:name="Validation"/>
<scripting:component doc:name="Script">
<scripting:script engine="Groovy"><![CDATA[throw new java.lang.IllegalArgumentException('bad arg')]]></scripting:script>
</scripting:component>
<logger level="INFO" doc:name="Logger"/>
</sub-flow>
<flow name="flowdemo" processingStrategy="synchronous">
<expression-component doc:name="Expression"><![CDATA[flowVars.dummy = flowVars.fake.test]]></expression-component>
<catch-exception-strategy doc:name="Catch Exception Strategy" >
<flow-ref name="exceFlow" doc:name="Flow Reference"/>
</catch-exception-strategy>
</flow>
<flow name="mdemoFlow" processingStrategy="synchronous">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="3" timeUnit="MINUTES"/>
<logger level="INFO" doc:name="Logger"/>
</poll>
<flow-ref name="flowdemo" doc:name="flowdemo"/>
<logger level="INFO" doc:name="Logger"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="test logging in error" level="ERROR" doc:name="Logger"/>
<logger level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</flow>
</mule>
flowdemo which is flow ( Not a subflow) and has its own catch Exception Stratergy(So it is being handled by the demo flow itself). Thread started from main flow (mdemoFlow) which is calling other flow Via flowRef hence it is back to the mainFlow to complete the thread which is expected(Irrespective of flow processing strategy). If you want to handled all the exception in the main flow itself. Please use the below config ( Make the flowdemo as subflow), so by default any exception happen in its associated subflow will be back to its main flow to handle the same.
<sub-flow name="flowdemo" >
<expression-component doc:name="Expression"><![CDATA[flowVars.dummy = flowVars.fake.test]]></expression-component>
</sub-flow>
<flow name="mdemoFlow" processingStrategy="synchronous">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="3" timeUnit="MINUTES"/>
<logger level="INFO" doc:name="Logger"/>
</poll>
<flow-ref name="flowdemo" doc:name="flowdemo"/>
<logger level="INFO" doc:name="Logger" message="***final logger***"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="test logging in error" level="ERROR" doc:name="Logger"/>
<logger level="INFO" doc:name="Logger"/>
<flow-ref name="exceFlow" doc:name="Flow Reference"/>
</catch-exception-strategy>
</flow>
<sub-flow name="exceFlow">
<logger level="ERROR" doc:name="Logger"/>
<logger level="INFO" doc:name="Logger"/>
</sub-flow>
To make Exception strategy as Global. You can use global exception strategy and call the same via reference Exception strategy. Please refer the link for more details https://docs.mulesoft.com/mule-user-guide/v/3.7/reference-exception-strategy
My flow looks like the below, I expect the message to be redelivered 2 times and then the
Redelivery is exhaused SAD
logger to be printed. But after the component throws the exception the re delivery mechanism does not kick in
<vm:connector name="VM" validateConnections="true" doc:name="VM" />
<flow name="TriggerFlow" >
<http:listener config-ref="Orders_HTTP_Listener_Configuration" path="/rollback" allowedMethods="GET" doc:name="1080/rollback" />
<vm:outbound-endpoint exchange-pattern="request-response" path="txFlow" doc:name="VM" connector-ref="VM" responseTimeout="60000">
</vm:outbound-endpoint>
</flow>
<flow name="TxFlow" >
<vm:inbound-endpoint exchange-pattern="request-response" path="txFlow" doc:name="case1" connector-ref="VM" responseTimeout="60000">
<xa-transaction action="ALWAYS_BEGIN"/>
</vm:inbound-endpoint>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[throw new RuntimeException();]]></scripting:script>
</scripting:component>
<rollback-exception-strategy maxRedeliveryAttempts="3" doc:name="Rollback Exception Strategy">
<logger message="Will rollback #[payload]" level="INFO" doc:name="Logger"/>
<on-redelivery-attempts-exceeded>
<logger message="Redelivery is exhaused SAD " level="INFO" doc:name="Logger"/>
</on-redelivery-attempts-exceeded>
</rollback-exception-strategy>
</flow>
I finally got the answer after speaking with MuleSoft. The updated flow should look like the below, both the VM's should be one-way and the processing strategy of the TxFlow should be synchronous. If the VM is request-reponse then it behaves more like a flow-ref with no queue involved and hence no redelivery ...
I have a mule flow which reads messages from a sonic topic and publish to a Websphere MQ Topic.
The flow is synchronous and transacted.
I have set maxRedelivery="10" in the inboud endpoint. but it keeps on trying to redeliver.
Here is the exception I get:
ERROR 2014-03-03 15:13:08,763 [JMS Session Delivery Thread - $TMPAPPID$544239$$SESSION$0:-3441129419112818566] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : "Message with id "ID:1419c04f:da190005:1448992ACB1" has been redelivered 1,511 times on endpoint "jms://topic:testtopic", which exceeds the maxRedelivery setting of 10 on the connector "sonicMQConnectorSub". Message payload is of type: TextMessage
Code : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. "Message with id "ID:1419c04f:da190005:1448992ACB1" has been redelivered 1,511 times on endpoint "jms://topic:testtopic", which exceeds the maxRedelivery setting of 10 on the connector "sonicMQConnectorSub". Message payload is of type: TextMessage (org.mule.transport.jms.redelivery.MessageRedeliveredException)
org.mule.transport.jms.redelivery.JmsXRedeliveryHandler:91 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/transport/jms/redelivery/MessageRedeliveredException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
org.mule.transport.jms.redelivery.MessageRedeliveredException: "Message with id "ID:1419c04f:da190005:1448992ACB1" has been redelivered 1,511 times on endpoint "jms://topic:testtopic", which exceeds the maxRedelivery setting of 10 on the connector "sonicMQConnectorSub". Message payload is of type: TextMessage
at org.mule.transport.jms.redelivery.JmsXRedeliveryHandler.handleRedelivery(JmsXRedeliveryHandler.java:91)
at org.mule.transport.jms.MultiConsumerJmsMessageReceiver$JmsWorker.preProcessMessage(MultiConsumerJmsMessageReceiver.java:426)
at org.mule.transport.AbstractReceiverWorker$1$1.process(AbstractReceiverWorker.java:120)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
Here is the flow I use.
<jms:connector name="sonicMQConnectorSub" specification="1.1" validateConnections="true" maxRedelivery="10" connectionFactory-ref="soniqMQConnectionFactorySub" doc:name="JMS" clientId="${topic.sub.clientId}" durable="true"/>
<spring:beans>
<spring:bean id="soniqMQConnectionFactoryBeanSub" name="soniqMQConnectionFactorySub" class="progress.message.jclient.ConnectionFactory">
<spring:property name="connectionURLs" value="${topic.sub.providerUrls}" />
<spring:property name="defaultUser" value="${topic.sub.username}" />
<spring:property name="defaultPassword" value="${topic.sub.password}" />
</spring:bean>
</spring:beans>
<jms:connector name="wsMQConnector" specification="1.1" username="${topic.pub.username}" password="${topic.pub.password}" validateConnections="true" connectionFactory-ref="wsMQConnectionFactory" doc:name="JMS" clientId="${topic.pub.clientId}"/>
<spring:beans>
<spring:bean id="wsMQConnectionFactory" class="com.ibm.mq.jms.MQTopicConnectionFactory">
<spring:property name="transportType" value="1"/>
<spring:property name="hostName" value="${topic.pub.host}"/>
<spring:property name="port" value="${topic.pub.port}"/>
<spring:property name="channel" value="${topic.pub.channel}"/>
<spring:property name="queueManager" value="${topic.pub.queueManager}"/>
</spring:bean>
</spring:beans>
<flow name="Flow1" doc:name="Flow1" processingStrategy="synchronous">
<jms:inbound-endpoint doc:name="JMS" connector-ref="sonicMQConnectorSub" topic="${topic.sub.name}" >
<jms:transaction action="ALWAYS_BEGIN" />
</jms:inbound-endpoint>
<message-properties-transformer doc:name="Message Properties">
<add-message-property key="SENTTIMESTAMP" value="#[server.dateTime]"/>
</message-properties-transformer>
<logger message="Payload: #[message.payload]" level="INFO" doc:name="Logger"/>
<jms:outbound-endpoint doc:name="JMS" connector-ref="wsMQConnector" topic="${topic.pub.name}">
<jms:transaction action="ALWAYS_JOIN" />
</jms:outbound-endpoint>
</flow>
This is expected behavior, the above exception is raised when the maximum redelivery count defined in maxRedelivery has been exceeded by your JMS provider. See the answer by David Dossot here: jms Mule max redelivery exceeded
EDIT: Simplified question.
Why on earth, the file written is garbage (binary serilized data) instead of the payload that was set in the Groovy component? This only happens if there is an "All" Flow component.
Flow:
XML:
<file:connector name="OutputFile" autoDelete="true" streaming="true" validateConnections="true" doc:name="File" writeToDirectory="#{systemProperties['user.home']}"/>
<flow name="AllProblemFlow1" doc:name="AllProblemFlow1">
<vm:inbound-endpoint exchange-pattern="one-way" path="in" doc:name="VM"/>
<all doc:name="All">
<processor-chain>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy">
<scripting:text><![CDATA[return payload + 1]]></scripting:text>
</scripting:script>
</scripting:component>
</processor-chain>
<processor-chain>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy">
<scripting:text><![CDATA[return payload + 2]]></scripting:text>
</scripting:script>
</scripting:component>
</processor-chain>
</all>
<logger message="All payload: #[payload]" level="INFO" doc:name="Logger"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy">
<scripting:text><![CDATA[return "new payload"]]></scripting:text>
</scripting:script>
</scripting:component>
<file:outbound-endpoint responseTimeout="10000" connector-ref="OutputFile" doc:name="File" outputPattern="output.txt" path="#{systemProperties['user.home']}"/>
</flow>
This is very tricky: the all message processor changes the very nature of the in-flight Mule message from a MuleMessage to a MuleMessageCollection. Changing the payload on a MuleMessageCollection is basically ineffective.
You need to forcefully replace the current MuleMessageCollection with a brand new MuleMessage. Use the following code for your last Groovy component:
<scripting:text><![CDATA[
return new org.mule.DefaultMuleMessage("new payload", muleContext)
]]></scripting:text>