Reputation: 2769
I am working on an app and in case any exception occurs it prints the exception message appropriately.Here is my custom filter
package filter;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.mule.api.MuleMessage;
public class ExceptionClass implements org.mule.api.routing.filter.Filter {
@Override
public boolean accept(MuleMessage message) {
Map<String,Object> payload=(Map<String,Object>)message.getPayload();
if(!payload.containsKey("productid"))
{
throw new java.lang.NullPointerException("no data found in payload "+payload.toString());
}
if(Integer.parseInt((String) payload.get("productid"))<5)
{
throw new IllegalArgumentException("invalid input to payload " +payload.toString());
}
return true;
}
}
Here is the configuration of app
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:json="http://www.mulesoft.org/schema/mule/json" 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:spring="http://www.springframework.org/schema/beans"
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/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="muleexceptionhandlingFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP" >
<http:response-builder statusCode="#[flowVars['statuscode']]" reasonPhrase="#[flowVars['reason']]"/>
</http:listener>
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
<custom-filter doc:name="Custom" class="filter.ExceptionClass"/>
<logger message="payload:#[payload]" level="INFO" doc:name="Logger"/>
<logger message="#[message]" level="INFO" doc:name="Logger"/>
<set-payload value="payload:#[payload]" doc:name="Set Payload"/>
</flow>
<choice-exception-strategy name="muleexceptionhandlingChoice_Exception_Strategy">
<catch-exception-strategy doc:name="Catch Missing Data Exception Strategy" logException="false" when="#[exception.causedBy(java.lang.NullPointerException)]">
<set-payload value="Missing data:#[payload]" doc:name="Set Payload"/>
<set-variable variableName="reason" value="missing input data" doc:name="Variable"/>
<set-variable variableName="statuscode" value="400" doc:name="Variable"/>
</catch-exception-strategy>
<catch-exception-strategy doc:name="Catch Invalid data Exception Strategy" logException="false" when="#[exception.causedBy(java.lang.IllegalArgumentException)}">
<set-payload value="Invalid Data:#[payload]" doc:name="Set Payload"/>
<set-variable variableName="reason" value="invalid input" doc:name="Variable"/>
<set-variable variableName="statuscode" value="400" doc:name="Variable"/>
</catch-exception-strategy>
</choice-exception-strategy>
</mule>
and here is the error message in case of nullpointer exception
ERROR 2017-07-25 17:35:49,595 [[muleexceptionhandling].HTTP_Listener_Configuration.worker.01] org.mule.exception.DefaultMessagingExceptionStrategy: ******************************************************************************** Message : no data found in payload {price=1000, productname=Shampoo} (java.lang.NullPointerException). Payload
: {price=1000, productname=Shampoo} Payload Type : java.util.HashMap Filter : filter.ExceptionClass@584d4f19 Element : /muleexceptionhandlingFlow/processors/1 @ muleexceptionhandling:null:null -------------------------------------------------------------------------------- Root Exception stack trace: java.lang.NullPointerException: no data found in payload {price=1000, productname=Shampoo} at filter.ExceptionClass.accept(ExceptionClass.java:23) at org.mule.routing.MessageFilter.accept(MessageFilter.java:93) at org.mule.processor.AbstractFilteringMessageProcessor.process(AbstractFilteringMe ..................................
Why is the exception not getting caught by exception handler
Please guide!
Upvotes: 0
Views: 2345
Reputation: 440
The reason that your exception strategy is not getting called is because you have your exception strategy outside your block. Update it as below:
<flow name="muleexceptionhandlingFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP" >
<http:response-builder statusCode="#[flowVars['statuscode']]" reasonPhrase="#[flowVars['reason']]"/>
</http:listener>
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
<custom-filter doc:name="Custom" class="filter.ExceptionClass"/>
<logger message="payload:#[payload]" level="INFO" doc:name="Logger"/>
<logger message="#[message]" level="INFO" doc:name="Logger"/>
<set-payload value="payload:#[payload]" doc:name="Set Payload"/>
<choice-exception-strategy name="muleexceptionhandlingChoice_Exception_Strategy">
<catch-exception-strategy doc:name="Catch Missing Data Exception Strategy" logException="false" when="#[exception.causedBy(java.lang.NullPointerException)]">
<set-payload value="Missing data:#[payload]" doc:name="Set Payload"/>
<set-variable variableName="reason" value="missing input data" doc:name="Variable"/>
<set-variable variableName="statuscode" value="400" doc:name="Variable"/>
</catch-exception-strategy>
<catch-exception-strategy doc:name="Catch Invalid data Exception Strategy" logException="false" when="#[exception.causedBy(java.lang.IllegalArgumentException)}">
<set-payload value="Invalid Data:#[payload]" doc:name="Set Payload"/>
<set-variable variableName="reason" value="invalid input" doc:name="Variable"/>
<set-variable variableName="statuscode" value="400" doc:name="Variable"/>
</catch-exception-strategy>
</choice-exception-strategy>
</flow>
I was just reading through blogs for your use-case and what struck me is that even though your code will work and will give you your result as expected, filters have been designed to just stop the flow if it returns false and by design it does not throw any exception. So you actually have two cleaner options to handle this scenario. (i) Use the Validation component, which is what mule intends you to use if you want to perform input validations.
So for your example, this will be the validation rule -
<validation:is-true config-ref="Validation_Configuration" expression="#[payload.containsKey('productid')]" message="payload doesnt have productid" doc:name="Validation"/>
More interestingly, you can put multiple validations in the same component using the All option:- like
<validation:all config-ref="Validation_Configuration" doc:name="Validation">
<validation:validations>
<validation:is-true expression="#[Integer.parseInt((String) payload.get("productid"))<5]" message="prod id less than 5"/>
<validation:is-true expression="#[payload.containsKey('productid')]" message="no product id"/>
</validation:validations>
</validation:all>
If you explore this component more, you will find ways to catch the validation exceptions using custom exceptions or just using the message string that is logged as part of the exception message.
(ii) Use a filter as you have used, but wrap it around a message-filter component as explained in the below blog: https://www.ricston.com/blog/playing-with-mule-filters/ In your example, you can achieve your exception with the below expression filter:
<message-filter doc:name="Message" throwOnUnaccepted="true">
<expression-filter expression="#[payload.containsKey("productid")]" doc:name="Expression"/>
</message-filter>
Upvotes: 3