I have a Mule flow which obtains an oauth token from a service which may throw a fault. However the exception is not caught in the flow even though there is a catch exception strategy at the end. Can someone explain why the exception is not caught? When I post XML via SOAP UI using an invalid token to trigger an exception, the request gets to the flow, but the exception is not caught. Instead I get a stack trace indicating an invalid token. Here is the flow:
<flow name="order-query">
<http:listener config-ref="HTTP_config"
path="order/request" doc:name="HTTP" />
<flow-ref name="oauth-token-service">
<cxf:jaxws-service doc:name="SPOP SOAP"
serviceClass="o.x.p.SpopWS">
<cxf:inInterceptors>
<spring:ref bean="HeaderInInterceptor" />
</cxf:inInterceptors>
<cxf:outInterceptors>
<spring:ref bean="faultOutInterceptor" />
<spring:ref bean="headerOutInterceptor" />
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<spring:ref bean="OutSoapFaultInterceptor" />
</cxf:outFaultInterceptors>
</cxf:jaxws-service>
<scripting:transformer>
<scripting:script engine="python">
...
</scripting:script>
<scripting:transformer>
<catch-exception-strategy>
<logger level="INFO" message=" Should be handled here #[payload]"/>
</catch-exception-strategy>
</flow>
are you sure the exception is not catched? the default behavior of catch-exception-strategy is to log the catched exception. This is the reason why you see the stack trace in logs.
for mule 3.8 and above: you can disable/enable this behavior either with a checkbox (Log Exceptions):
or in XML (logException=false):
<catch-exception-strategy logException="false" doc:name="Catch Exception Strategy">
<logger level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
for mule 3.7: take a look here: https://stackoverflow.com/a/42181054/804521
Related
I am using mule request response VM and need the rollback messages to be reprocessed by VM in case of some exceptions, say connection issues. However, the rollback exception strategy does not appear to work when I use exchange pattern as request response for VM. The reason I used request response is I need way to know when all my VM messages have been processed and initiate another task after that. I think the behavior is that when there is an exception, the rollback strategy catches the exception and probably commits it. I do not see it trying the redeliver the message back to VM. It does work good when the exchange pattern is one-way.
<flow name="vmtransactionrollbackFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/myvm" doc:name="HTTP"/>
<set-payload value="Dummy list payload" doc:name="Set Payload"/>
<foreach doc:name="For Each">
<vm:outbound-endpoint exchange-pattern="request-response" path="myvm" connector-ref="VM" doc:name="VM">
<vm:transaction action="ALWAYS_BEGIN"/>
</vm:outbound-endpoint>
</foreach>
<logger message="DO SOMETHING ONLY AFTER ALL MESSAGES IN VM ARE PROCESSED" level="INFO" doc:name="Logger"/>
</flow>
<flow name="vmtransactionrollbackFlow1">
<vm:inbound-endpoint exchange-pattern="request-response" path="myvm" connector-ref="VM" doc:name="VM">
<vm:transaction action="BEGIN_OR_JOIN"/>
</vm:inbound-endpoint>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[throw new java.lang.Exception("Test exception");]]></scripting:script>
</scripting:component>
<rollback-exception-strategy maxRedeliveryAttempts="3" doc:name="Rollback Exception Strategy">
<logger message="Rolling back #[payload]" level="INFO" doc:name="Logger"/>
<on-redelivery-attempts-exceeded>
<logger message="Redelivery exhausted:#[payload]" level="INFO" doc:name="Logger"/>
</on-redelivery-attempts-exceeded>
</rollback-exception-strategy>
</flow>
Yes I ran into a similar problem, when the VM outbound uses a request-response exchange pattern it behaves more like flow-ref with no "queue" involved per say and hence no redelivery mechanism.
So if the VM's are configured as one-way and the flow processing strategy is synchronous (VM inbound flow), then the redelivery does kick in.
To achieve what you want you could use until-successful scope within the vmtransactionrollbackFlow1 flow, especially for the case of intermittent connection losses this is actually the recommended approach. In which you do not need transactions at all.
Do let us know how it goes, and if you found some other work around.
I have a custom Interceptor, from which I throw an Exception;
The Action(s) running that Interceptor is managed by Convention plugin;
The Exception raised by the Interceptor is globally defined in struts.xml for the package the Action is running into.
RESULT: the exception mapping is ignored and I get the
Struts Problem Report
Struts has detected an unhandled exception:
...
Stacktraces
java.lang.IllegalArgumentException: my message
I guess I'm just missing something stupid... we've already discussed of this in a similar question, but it's still not clear if it can or can't work this way:
struts.xml
<package name="my-package" namespace="my" extends="struts-default">
<interceptors>
<interceptor name="myInterceptor" class="foo.bar.MyInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"/>
<global-results>
<result name="input">/WEB-INF/content/my-input.jsp</result>
<result name="error">/WEB-INF/content/my-error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.IllegalArgumentException"
result="error" />
<exception-mapping exception="java.lang.Exception" result="error" />
</global-exception-mappings>
</package>
Action
#ParentPackage("my-package")
#Namespace("/my/blabla/yadayada")
public class MyAction extends MyBaseAction {
}
Interceptor
#Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
// ....
if (somethingWrong) {
throw new IllegalArgumentException("All work and no play makes Jack a dull boy");
}
}
I've also tried defining global result / global exception mapping in the abstract BaseAction, or in the physical real Action itself, but they're ignored too.
Any idea on what to add / remove / change in order to make it work as it should ? This is not esoteric stuff, this is basic :|
The main candidate for exception mapping feature is actions throwing an exceptions.
Docs:
Exception mappings is a powerful feature for dealing with an Action class that throws an Exception. The core idea is that an Exception thrown during the Action method can be automatically caught and mapped to a predefined Result.
But exceptions thrown from interceptors can be also handled by exception interceptor. In order to catch other interceptors exceptions exception interceptor should be defined as the first interceptor in the stack.
From the ExceptionMappingInterceptor javadoc:
It is recommended that you make this interceptor the first interceptor on the stack, ensuring that it has full access to catch any exception, even those caused by other interceptors.
I can not catch a basic org.mule exception triggered by a Poller component, Mule is still using the default mechanism (tried both Global or Local)
In case the below exception is thrown I would like to print something personal in the Log it self just for testing purpose, further enhancements will occur once this is working properly.
Message : Failed to move file "C:\Users\Administrator\Desktop\shared_folder\12131551.XML" to "C:\Users\Administrator\Desktop\archive\backup\12131551.XML.backup". The file might already exist.
Code : MULE_ERROR-3
Exception stack is:
1. Failed to move file "C:\Users\Administrator\Desktop\shared_folder\12131551.XML" to "C:\Users\Administrator\Desktop\archive\backup\12131551.XML.backup". The file might already exist. (org.mule.api.DefaultMuleException)
org.mule.transport.file.FileMessageReceiver:553 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/DefaultMuleException.html)
Root Exception stack trace:
org.mule.api.DefaultMuleException: Failed to move file "C:\Users\Administrator\Desktop\shared_folder\12131551.XML" to "C:\Users\Administrator\Desktop\archive\backup\12131551.XML.backup". The file might already exist.
at org.mule.transport.file.FileMessageReceiver.moveAndDelete(FileMessageReceiver.java:553)
at org.mule.transport.file.FileMessageReceiver.access$400(FileMessageReceiver.java:62)
at org.mule.transport.file.FileMessageReceiver$2.process(FileMessageReceiver.java:414)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
This is my PoC
<file:connector name="XML_poller" autoDelete="false" streaming="false" validateConnections="true" pollingFrequency="5000" doc:name="File"/>
<file:connector name="output" doc:name="File" autoDelete="false" streaming="false" validateConnections="true"/>
<flow name="exceptionStrategyExample" doc:name="exceptionStrategyExample">
<file:inbound-endpoint connector-ref="XML_poller" path="C:\Users\Administrator\Desktop\shared_folder" moveToDirectory="C:\Users\Administrator\Desktop\archive\backup"
moveToPattern="#[header:originalFilename].backup" doc:name="Poller" responseTimeout="10000">
<file:filename-wildcard-filter pattern="*.xml" caseSensitive="false"/>
</file:inbound-endpoint>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" method="POST" doc:name="HTTP"/>
<choice-exception-strategy>
<rollback-exception-strategy
when="exception.causedBy(java.lang.IllegalStateException)"
maxRedeliveryAttempts="3">
<logger message="Retrying shipping cost calc." level="WARN" />
<on-redelivery-attempts-exceeded>
<logger message="Too many retries shipping cost calc."
level="WARN" />
<set-payload value="Error: #[exception.summaryMessage]"/>
</on-redelivery-attempts-exceeded>
</rollback-exception-strategy>
<catch-exception-strategy doc:name="Catch Exception Strategy" when="exception.causedBy(org.mule.*)">
<logger message="************TEST***************" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
</flow>
It is simply not doing anything.... Any hints ?
I think this is a case of a System Exception, where no message is created that could be caught by the exception handling components (see Mule docs for System vs Messaging exceptions). You could try either writing a custom message receiver overriding the processFile method (see this post for inspiration), or check the existence of duplicate files manually and use a separate file:outbound-endpoint for writing the file.
I have found a workaround. Insert a processor chain element before file connector and put a dummy set-payload. In this way you will always create a message and then it ll not use DefaultExceptionStrategy for handling the errors.
Is it possible to configure logback to log at e.g. WARN or INFO level for all packages but x.y? And then separate configuration for package x.y only.
I don't know of any way you can get the "NOT" package aspect of your question, but I routinely log one package at DEBUG and all the rest at INFO and...above is it...WARN and ERROR. This is straight up-the-middle logback. My loggers are all like...
package rekdev.org.service.api;
public class DefaultConfigResource {
// ...
private static final Logger log = LoggerFactory.getLogger( DefaultConfigResource.class );
// ...
}
...on a logback.xml configuration like...
<logger name="rekdev.org.service.api" level="debug" />
...
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="DAILY_ROLLING" />
<appender-ref ref="SYSLOG" />
</root>
Has the effect of most output popping out at INFO, WARN, ERROR but all the rekdev.org.service.api classes. All the classes in the rekdev.org.service.api package produce output at DEBUG, INFO, WARN, ERROR.
Or did I misunderstand your questions entirely?
i declare a global exception handler in web.xml
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/exceptionHandler</location>
</error-page>
it works fine most of the time. But it cannot capture the exceptions thrown from the prepare method in struts2 actions
anyone know why
Probably because Struts2's ExceptionMappingInterceptor catches exceptions and maps them to error pages itself.
You can use the following in your struts.xml:
<global-results>
<result name="error">/WEB-INF/error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="error"/>
</global-exception-mappings>
Alternatively, you could remove the ExceptionMappingInterceptor from the interceptor stack if you really want to use the web.xml method.