I have a quartz scheduler configured as shown below.
<quartz:inbound-endpoint jobName="retryJob" repeatInterval="5000" cronExpression="0 0/1 * * * ?">
<quartz:endpoint-polling-job>
<quartz:job-endpoint ref="retryQueue"/>
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
<flow-ref name="callMySubFlow" />
<choice-exception-strategy>
<catch-exception-strategy when="groovy:message.getInvocationProperty('next') == 'DONE'">
<logger level="INFO" message="DONE"/>
</catch-exception-strategy>
<rollback-exception-strategy>
<on-redelivery-attempts-exceeded>
<logger level="INFO" message="Redelivery Exceeded. Done with retries."/>
</on-redelivery-attempts-exceeded>
</rollback-exception-strategy>
</choice-exception-strategy>
<jms:connector name="queueConnectorU" connectionFactory-ref="MQConnectionFactoryU" specification="1.1" username="me" password="p" numberOfConsumers="5" maxRedelivery="3"/>
<jms:endpoint name="retryQueue" queue="retryQ" connector-ref="queueConnectorU">
<ee:multi-transaction action="ALWAYS_BEGIN" />
</jms:endpoint>
I have an intentional service not found exception in subflow and expect the message to be retried 3 times and commited, but the message is never removed from the queue...infinite loop.
Is there anything wrong with the configuration?
Related
I am trying to capture error status from one API & and send it to the calling API. In my downstream API I have the following catch exception strategy:
<catch-exception-strategy>
<set-payload value= "500" />
<logger message="***BACKEND API: #[payload]" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
In my calling API I have the following:
<http:request config-ref="downstream API " path="/downstream/{id}" method="POST " doc:name="Generate "/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<logger message="PAYLOAD: #[payload]" level="INFO" doc:name="Logger"/>
However I am able to print the payload in the downstream API but not in the calling API. Am I missing something?
If your API throw http.status == 500, it should trigger this condition
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="#[message.inboundProperties.'http.status' == 500]" doc:name="Error 500">
<set-payload value= "500" />
<logger message="***BACKEND API: #[payload]" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
I you didn't add any condition, it should be the default catch exception
everything should work properly.
I have a mule project where a flow with a rollback exception is causing an exception to be thrown in the flow that references it. Is this normal behaviour?
Here is the code:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:file="http://www.mulesoft.org/schema/mule/file"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="CE-3.5.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/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd">
<file:connector name="File" autoDelete="true" streaming="false" validateConnections="true" doc:name="File"/>
<flow name="rollbacktestFlow2" doc:name="rollbacktestFlow2">
<file:inbound-endpoint path="C:\RollbackTEst\In" responseTimeout="10000" doc:name="File" connector-ref="File"/>
<logger message="File Rx" level="INFO" doc:name="FileRx"/>
<flow-ref name="rollbacktestFlow1" doc:name="Flow Reference"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="Rollbacktestflow 2" level="INFO" doc:name="Rollbacktestflow2"/>
</catch-exception-strategy>
</flow>
<flow name="rollbacktestFlow1" doc:name="rollbacktestFlow1" >
<logger message="Rollback trigger" level="INFO" doc:name="RollbackTrigger"/>
<expression-component doc:name="Expression"><![CDATA[forceException]]></expression-component>
<rollback-exception-strategy maxRedeliveryAttempts="4" doc:name="Rollback Exception Strategy">
<logger message="retry" level="INFO" doc:name="retry"/>
<expression-component doc:name="Copy_of_Expression"><![CDATA[forceException]]></expression-component>
<on-redelivery-attempts-exceeded doc:name="Redelivery exhausted">
<logger message="exhausted" level="INFO" doc:name="exhausted"/>
</on-redelivery-attempts-exceeded>
</rollback-exception-strategy>
</flow>
Should the rollback section of the exception not be executed 4 times and then the redelivery exhausted exception be thrown?
Here is the log:
INFO 2014-11-12 15:36:40,529 [main] org.mule.module.launcher.MuleDeploymentService:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Started app 'rollbacktest' +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
INFO 2014-11-12 15:36:40,544 [main] org.mule.module.launcher.DeploymentDirectoryWatcher:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Mule is up and kicking (every 5000ms) +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
INFO 2014-11-12 15:37:18,031 [[rollbacktest].File.receiver.01] org.mule.transport.file.FileMessageReceiver: Lock obtained on file: C:\RollbackTEst\In\New Text Document.txt
INFO 2014-11-12 15:37:18,048 [[rollbacktest].rollbacktestFlow2.stage1.02] org.mule.api.processor.LoggerMessageProcessor: File Rx
INFO 2014-11-12 15:37:18,048 [[rollbacktest].rollbacktestFlow2.stage1.02] org.mule.api.processor.LoggerMessageProcessor: Rollback trigger
ERROR 2014-11-12 15:37:18,079 [[rollbacktest].rollbacktestFlow2.stage1.02] org.mule.exception.RollbackMessagingExceptionStrategy:
********************************************************************************
Message : Execution of the expression "forceException" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[]
Code : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. [Error: unresolvable property or identifier: forceException]
[Near : {... forceException ....}]
^
[Line: 1, Column: 1] (org.mule.mvel2.PropertyAccessException)
org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer:692 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/mvel2/PropertyAccessException.html)
2. Execution of the expression "forceException" failed. (org.mule.api.expression.ExpressionRuntimeException)
org.mule.el.mvel.MVELExpressionLanguage:202 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/expression/ExpressionRuntimeException.html)
3. Execution of the expression "forceException" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[] (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:
[Error: unresolvable property or identifier: forceException]
[Near : {... forceException ....}]
^
[Line: 1, Column: 1]
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getBeanProperty(ReflectiveAccessorOptimizer.java:692)
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:337)
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:140)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
INFO 2014-11-12 15:37:18,079 [[rollbacktest].rollbacktestFlow2.stage1.02] org.mule.api.processor.LoggerMessageProcessor: retry
ERROR 2014-11-12 15:37:18,079 [[rollbacktest].rollbacktestFlow2.stage1.02] org.mule.exception.RollbackMessagingExceptionStrategy: Failed to dispatch message to error queue after it failed to process. This may cause message loss.Logging Message here:
org.mule.DefaultMuleMessage
{
id=c8cf45f1-6a81-11e4-887d-005056b6086b
payload=[B
correlationId=<not set>
correlationGroup=-1
correlationSeq=-1
encoding=UTF-8
exceptionPayload=org.mule.message.DefaultExceptionPayload#1975a694
Message properties:
INVOCATION scoped properties:
originalFilename=New Text Document.txt
INBOUND scoped properties:
MULE_ORIGINATING_ENDPOINT=endpoint..C.Users.mik119.Desktop.RollbackTEst.In
directory=C:\RollbackTEst\In
fileSize=0
originalFilename=New Text Document.txt
timestamp=1415806637595
OUTBOUND scoped properties:
MULE_ENCODING=UTF-8
SESSION scoped properties:
}
org.mule.api.MessagingException: Execution of the expression "forceException" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[]
at org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:32)
at org.mule.execution.MessageProcessorNotificationExecutionInterceptor.execute(MessageProcessorNotificationExecutionInterceptor.java:58)
at org.mule.execution.MessageProcessorExecutionTemplate.execute(MessageProcessorExecutionTemplate.java:44)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:94)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:67)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.doProcess(InterceptingChainLifecycleWrapper.java:50)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:67)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.access$001(InterceptingChainLifecycleWrapper.java:22)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper$1.process(InterceptingChainLifecycleWrapper.java:66)
at org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:24)
at org.mule.execution.MessageProcessorNotificationExecutionInterceptor.execute(MessageProcessorNotificationExecutionInterceptor.java:58)
at org.mule.execution.MessageProcessorExecutionTemplate.execute(MessageProcessorExecutionTemplate.java:44)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.process(InterceptingChainLifecycleWrapper.java:61)
at org.mule.exception.TemplateMessagingExceptionStrategy.route(TemplateMessagingExceptionStrategy.java:139)
at org.mule.exception.RollbackMessagingExceptionStrategy.route(RollbackMessagingExceptionStrategy.java:104)
at org.mule.exception.TemplateMessagingExceptionStrategy.handleException(TemplateMessagingExceptionStrategy.java:45)
at org.mule.execution.HandleExceptionInterceptor.execute(HandleExceptionInterceptor.java:37)
at org.mule.execution.HandleExceptionInterceptor.execute(HandleExceptionInterceptor.java:14)
at org.mule.execution.BeginAndResolveTransactionInterceptor.execute(BeginAndResolveTransactionInterceptor.java:54)
at org.mule.execution.SuspendXaTransactionInterceptor.execute(SuspendXaTransactionInterceptor.java:50)
at org.mule.execution.RethrowExceptionInterceptor.execute(RethrowExceptionInterceptor.java:28)
at org.mule.execution.RethrowExceptionInterceptor.execute(RethrowExceptionInterceptor.java:13)
at org.mule.execution.ErrorHandlingExecutionTemplate.execute(ErrorHandlingExecutionTemplate.java:59)
at org.mule.execution.ErrorHandlingExecutionTemplate.execute(ErrorHandlingExecutionTemplate.java:30)
at org.mule.construct.Flow.process(Flow.java:76)
at org.mule.config.spring.factories.FlowRefFactoryBean$2.process(FlowRefFactoryBean.java:145)
at org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:24)
at org.mule.execution.MessageProcessorNotificationExecutionInterceptor.execute(MessageProcessorNotificationExecutionInterceptor.java:58)
at org.mule.execution.MessageProcessorExecutionTemplate.execute(MessageProcessorExecutionTemplate.java:44)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:94)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:67)
at org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:24)
at org.mule.execution.MessageProcessorExecutionTemplate.execute(MessageProcessorExecutionTemplate.java:44)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:102)
at org.mule.interceptor.AbstractEnvelopeInterceptor.process(AbstractEnvelopeInterceptor.java:51)
at org.mule.processor.AsyncInterceptingMessageProcessor.processNextTimed(AsyncInterceptingMessageProcessor.java:118)
at org.mule.processor.AsyncInterceptingMessageProcessor$AsyncMessageProcessorWorker$1.process(AsyncInterceptingMessageProcessor.java:189)
at org.mule.processor.AsyncInterceptingMessageProcessor$AsyncMessageProcessorWorker$1.process(AsyncInterceptingMessageProcessor.java:182)
at org.mule.execution.ExecuteCallbackInterceptor.execute(ExecuteCallbackInterceptor.java:16)
at org.mule.execution.HandleExceptionInterceptor.execute(HandleExceptionInterceptor.java:30)
at org.mule.execution.HandleExceptionInterceptor.execute(HandleExceptionInterceptor.java:14)
at org.mule.execution.BeginAndResolveTransactionInterceptor.execute(BeginAndResolveTransactionInterceptor.java:54)
at org.mule.execution.ResolvePreviousTransactionInterceptor.execute(ResolvePreviousTransactionInterceptor.java:44)
at org.mule.execution.SuspendXaTransactionInterceptor.execute(SuspendXaTransactionInterceptor.java:50)
at org.mule.execution.ValidateTransactionalStateInterceptor.execute(ValidateTransactionalStateInterceptor.java:40)
at org.mule.execution.IsolateCurrentTransactionInterceptor.execute(IsolateCurrentTransactionInterceptor.java:41)
at org.mule.execution.ExternalTransactionInterceptor.execute(ExternalTransactionInterceptor.java:48)
at org.mule.execution.RethrowExceptionInterceptor.execute(RethrowExceptionInterceptor.java:28)
at org.mule.execution.RethrowExceptionInterceptor.execute(RethrowExceptionInterceptor.java:13)
at org.mule.execution.TransactionalErrorHandlingExecutionTemplate.execute(TransactionalErrorHandlingExecutionTemplate.java:109)
at org.mule.execution.TransactionalErrorHandlingExecutionTemplate.execute(TransactionalErrorHandlingExecutionTemplate.java:30)
at org.mule.processor.AsyncInterceptingMessageProcessor$AsyncMessageProcessorWorker.doRun(AsyncInterceptingMessageProcessor.java:181)
at org.mule.work.AbstractMuleEventWork.run(AbstractMuleEventWork.java:39)
at org.mule.work.WorkerContext.run(WorkerContext.java:286)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.mule.api.expression.ExpressionRuntimeException: Execution of the expression "forceException" failed.
at org.mule.el.mvel.MVELExpressionLanguage.evaluateInternal(MVELExpressionLanguage.java:202)
at org.mule.el.mvel.MVELExpressionLanguage.evaluate(MVELExpressionLanguage.java:154)
at org.mule.el.mvel.MVELExpressionLanguage.evaluate(MVELExpressionLanguage.java:133)
at org.mule.el.ExpressionLanguageComponent.process(ExpressionLanguageComponent.java:51)
at org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:24)
... 56 more
Caused by: [Error: unresolvable property or identifier: forceException]
[Near : {... forceException ....}]
^
[Line: 1, Column: 1]
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getBeanProperty(ReflectiveAccessorOptimizer.java:692)
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:337)
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:140)
at org.mule.mvel2.ast.ASTNode.optimize(ASTNode.java:159)
at org.mule.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:115)
at org.mule.mvel2.MVELRuntime.execute(MVELRuntime.java:86)
at org.mule.mvel2.compiler.CompiledExpression.getDirectValue(CompiledExpression.java:123)
at org.mule.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:119)
at org.mule.mvel2.MVEL.executeExpression(MVEL.java:943)
at org.mule.el.mvel.MVELExpressionExecutor.execute(MVELExpressionExecutor.java:72)
at org.mule.el.mvel.MVELExpressionLanguage.evaluateInternal(MVELExpressionLanguage.java:198)
... 60 more
ERROR 2014-11-12 15:37:18,095 [[rollbacktest].rollbacktestFlow2.stage1.02] org.mule.exception.CatchMessagingExceptionStrategy:
********************************************************************************
Message : Execution of the expression "forceException" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[]
Code : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. [Error: unresolvable property or identifier: forceException]
[Near : {... forceException ....}]
^
[Line: 1, Column: 1] (org.mule.mvel2.PropertyAccessException)
org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer:692 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/mvel2/PropertyAccessException.html)
2. Execution of the expression "forceException" failed. (org.mule.api.expression.ExpressionRuntimeException)
org.mule.el.mvel.MVELExpressionLanguage:202 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/expression/ExpressionRuntimeException.html)
3. Execution of the expression "forceException" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[] (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:
[Error: unresolvable property or identifier: forceException]
[Near : {... forceException ....}]
^
[Line: 1, Column: 1]
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getBeanProperty(ReflectiveAccessorOptimizer.java:692)
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:337)
at org.mule.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:140)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
INFO 2014-11-12 15:37:18,095 [[rollbacktest].rollbacktestFlow2.stage1.02] org.mule.api.processor.LoggerMessageProcessor: Rollbacktestflow 2
The exhausted logger is not getting called, instead the Rollbacktestflow2 logger in the initial flow is called.
Can anyone explain why? Thanks
Why the rollback-exception-strategy doesn't retry?:
The rollback-exception-strategy behaves differently depending on if the flow has a transaction or not, and on the kind of inbound connector ( transactional or reliable ).
To be able to reprocess the message, you need an inbound transport, so the rollback-exception-strategy can either rollback the transaction ( transactional transport with an open transaction ) or discard the message and try again ( reliable transport )
In your example you don't have an inbound connector on the second flow, so the rollback-exception-strategybehaves as section "Use Rollback Exception Strategy for Unhandled Exceptions" on the mule doc describes: "When the flow exchange pattern is request-response, rollback exception strategy changes the payload of a message and returns it to the client"
Although the doc is not explicit, when the flow doesn't have an inbound connector the rollback-exception-strategy doesn't retry.
If you want to implement a flow that retries, you can use a vm transport between the two flows.
Example:
<mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns:https="http://www.mulesoft.org/schema/mule/https"
xmlns:file="http://www.mulesoft.org/schema/mule/file"
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.5.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/https http://www.mulesoft.org/schema/mule/https/current/mule-https.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/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd">
<file:connector name="File" autoDelete="true" streaming="false" validateConnections="true" doc:name="File"/>
<flow name="pickFiles" >
<file:inbound-endpoint path="/Users/ramiro/tmp/rollback/in" responseTimeout="10000" doc:name="File" connector-ref="File"/>
<logger message="File Rx" level="INFO" doc:name="FileRx"/>
<vm:outbound-endpoint path="buffer" exchange-pattern="one-way" doc:name="VM"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="Rollbacktestflow 2" level="INFO" doc:name="Rollbacktestflow2"/>
</catch-exception-strategy>
</flow>
<flow name="processQueue" >
<vm:inbound-endpoint path="buffer" exchange-pattern="one-way" doc:name="VM">
<vm:transaction action="ALWAYS_BEGIN" />
</vm:inbound-endpoint>
<logger message="about to throw Exception..." level="INFO" doc:name="RollbackTrigger"/>
<scripting:component doc:name="throw Exception">
<scripting:script engine="Groovy"><![CDATA[
throw new Exception('some very bad error')
]]></scripting:script>
</scripting:component>
<!-- we never get here -->
<file:outbound-endpoint path="/Users/ramiro/tmp/rollback/success " doc:name="dlq" connector-ref="File"/>
<rollback-exception-strategy maxRedeliveryAttempts="4" doc:name="Rollback Exception Strategy">
<logger message="retry" level="INFO" doc:name="retry"/>
<on-redelivery-attempts-exceeded >
<logger message="exhausted" level="INFO" doc:name="exhausted"/>
<file:outbound-endpoint path="/Users/ramiro/tmp/rollback/dlq" doc:name="dlq" connector-ref="File"/>
</on-redelivery-attempts-exceeded>
</rollback-exception-strategy>
</flow>
</mule>
Here we get a file and send it via a vm transport. The second flow picks the message from the vm and if there's an exception ( always in the example ), will abort the transaction and try to process again the message, and if it fails 4 times then send it to a DLQ.
About until-successful
You say that you used until-successful as a workaround. In my opinion using rollback-exception-strategy is more appropriate when you have a unit of work that you need to handle as a transaction ( maybe a flow with several transformations and enrichments ), and until-successful when you just need to retry a step that may fail ( like calling a REST service that may fail because of a temporary network condition )
I have a simple csv-to-pojo datamapper, which gets sent to two synchronous flow through an "All" flow control component. The first flow runs the payload through a Foreach, then once it is done, the second flow attempts to run the payload from the datamapper again through a different foreach, but instead I'm getting this warning message:
Splitter returned no results. If this is not expected, please check your split expression.
Furthermore, it seems that Mule only allows me to run the payload through either flow one or flow two, but not both. Again, running it trough more than one Foreach component will result in the Splitter warning.
Any help will be appreciated. Thanks in advance. Here's the setup:
<flow name="main_flow" doc:name="main_flow" initialState="started" processingStrategy="synchronous">
<data-mapper:transform config-ref="csv_to_pojo" doc:name="CSV To Pojo" stream="true"/>
<all doc:name="All">
<flow-ref name="flow1" doc:name="Flow Reference"/>
<flow-ref name="flow2" doc:name="Flow Reference"/>
</all>
</flow>
<flow name="flow1" doc:name="flow1" processingStrategy="synchronous">
<logger message="Entering flow 1" level="INFO" doc:name="Logger"/>
<foreach doc:name="For Each">
<logger message="Inside foreach of flow1 " level="INFO" doc:name="Logger"/>
</foreach>
</flow>
<flow name="flow2" doc:name="flow2" processingStrategy="synchronous">
<logger message="Entering flow2" level="INFO" doc:name="Logger"/>
<foreach doc:name="For Each">
<logger message="Inside foreach of flow2" level="INFO" doc:name="Logger"/>
</foreach>
</flow>
In my Mule app, I've configured some of the flows to use a catch exception strategy in order to do some special processing. For these cases, I want to pop the error and the original payload into an object store. Everywhere else, the default exception strategy is fine.
<flow name="saveLookup">
<vm:inbound-endpoint exchange-pattern="one-way" ref="Lookup_Save_VM" />
<component>
<spring-object bean="insertLookupMDCvalues"/>
</component>
<set-variable variableName="originalPayload" value="#[payload]"/>
<json:json-to-object-transformer returnClass="com.company.LookupData"/>
<set-variable variableName="transactionId" value="#[payload.transactionId]"/>
<transactional action="ALWAYS_BEGIN">
<logger message="${lookup.SQL}" level="INFO"/>
<jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="saveLookup" queryTimeout="-1" connector-ref="JdbcConnector" />
<foreach collection="#[payload.transactional.lookupItems.items]">
<logger message="${lookup.item.SQL}" level="INFO" />
<jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="saveLookupItem" queryTimeout="-1" connector-ref="JdbcConnector"/>
</foreach>
</transactional>
<component>
<spring-object bean="clearLookupMDCvalues"/>
</component>
<catch-exception-strategy>
<message-properties-transformer scope="invocation">
<add-message-property key="errorMap" value="#[['id' : transactionId, 'body' : originalPayload, 'error' : exception.summaryMessage]]"/>
</message-properties-transformer>
<choice>
<when expression="#[message.inboundProperties['resubmit']]">
<logger message="Resubmission of lookup data failed, saving to Dead Letter object store. ID=#[transactionId]" level="INFO"/>
<objectstore:store config-ref="lookupDeadLetterOS" key="#[transactionId]" overwrite="true" value-ref="#[errorMap]"/>
</when>
<otherwise>
<logger message="Saving lookup data failed, saving to Error object store. ID=#[transactionId]" level="INFO"/>
<objectstore:store config-ref="lookupErrorOS" key="#[transactionId]" overwrite="true" value-ref="#[errorMap]"/>
</otherwise>
</choice>
<set-payload value="Error: #[exception.summaryMessage]"/>
<component>
<spring-object bean="clearLookupMDCvalues"/>
</component>
</catch-exception-strategy>
</flow>
My problem is that when an error is encountered, let's say a Null Pointer Exception in the foreach component, I'm seeing four ERROR log statements for each event:
Exception stack is: 1. null (java.lang.NullPointerException) ...and so on. This is logged twice.
CatchMessagingExceptionStrategy - Message : Execution of the expression "payload.transactional.lookupItems.items" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: LookupData
DefaultMessagingExceptionStrategy - Message : Execution of the expression "payload.transactional.lookupItems.items" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: LookupData
I thought that a flow-specific exception strategy should override the default strategy. Why the duplicate log messages, and is there a way to shush them? I'd like to avoid having to configure the default exception strategy, as it's perfectly acceptable behavior in the majority of the flows.
The issue is that the built in exception strategies inherit from AbstractExceptionListener, and they all use the logException template method. The base implementation always logs at ERROR level, which is sometimes not appropriate for your application.
You can create a simple subclass of CatchMessagingExceptionStrategy that overrides the logException method, and logs however you want. Then, use it in your flow in place of the <catch-exception-strategy> like so:
<custom-exception-strategy class="com.mycompany.mule.QuietCatchExceptionStrategy">
<!-- your message processors here -->
</custom-exception-strategy>
I've been struggling through SO and the Mule forums but can't find a solution that works. The esb takes in a single request containing an id, which creates an XML payload that is composed a list of related ids. This XML payload is then split and sent to a transformer that takes each related id to get some meta data. The results are then supposed to be combined together to make an XML response. The problem I am having is that no matter how I transform the final result set, I always get back the document with an encapsulating string "??sr)java.util.concurrent.CopyOnWriteArrayListx]....""x
Any ideas/comments would be greatly appreciated.
Here is the mule-config I am using:
<http:connector name="HttpConnector" doc:name="HTTP\HTTPS"/>
<expression-transformer name="ExtractId" doc:name="Expression">
<return-argument evaluator="xpath" expression="//string[1]"/>
</expression-transformer>
<flow name="myFlow1" doc:name="myFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="incoming/path/" connector-ref="HttpConnector" doc:name="HTTP"/>
<custom-transformer encoding="UTF-8" class="mycomponents.transformers.SubscriberRequestTransformer" doc:name="Create Hub Id Requests"/>
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
<splitter evaluator="xpath" expression="//entry/list/string" enableCorrelation="ALWAYS" doc:name="Splitter"/>
<transformer ref="ExtractId" doc:name="Transformer Reference"/>
<logger message="#[payload:]" level="INFO" doc:name="Logger"/>
<custom-transformer encoding="UTF-8" class="mycomponents.transformers.HubQueryProcessor" doc:name="Create Hub Id Requests"/>
<collection-aggregator />
<component class="mycomponents.TopicResponseAggregatorComponent" doc:name="Collect requests" />
<logger message="Aggregated Content (#[groovy:payload.size()] elements): \n#[payload:]" level="INFO" doc:name="Logger"/>
<logger message="#[payload:]" level="INFO" doc:name="Logger"/>
</flow>
I've resolved the issue. Although I don't quite understand why it's different but I'm assuming it has to do with some of the mule "magic". I split up the flow into multiple flows which is what I was eventually going to do anyways. However, by doing this the problem went away.
FYI: here's the updated flow:
<flow name="myFlow1" doc:name="myFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="url/for/service/" connector-ref="HttpConnector" doc:name="HTTP"/>
<flow-ref name="createHubIdRequestsFlow" doc:name="Map To Hub Ids" doc:description="Takes in the situation id passed in by the client. Does the query lookup versus the content mapping tables. creates the correspondng requests for meta data information to the provider(s)"/>
<flow-ref name="getTopicRequests" doc:name="Process Provider Reponses" doc:description="For each JSON response returned from the provider, transform it into an XML representation of that data"/>
<flow-ref name="buildResponseFlow" doc:name="Build final response" doc:description="piece all the messages together into a single object as a string"/>
<response>
<message-properties-transformer>
<add-message-property value="text/xml" key="Content-Type" />
</message-properties-transformer>
</response>
</flow>
By default, the message properties transformer stores new properties in the "invocation" scope. You need to set the content-type on the "outbound" scope so it is used by the inbound HTTP endpoint in its response phase.
Try this:
<response>
<message-properties-transformer scope="outbound">
<add-message-property value="text/xml" key="Content-Type" />
</message-properties-transformer>
</response>