Mulesoft - How to find Http error payload in exception object? - mule

How to find Http error payload in exception object ?
System 1 -> Call's Mule server . Mule server -> Docusign / some one else.
Docusign / some one returns 400 error with json payload (includes errorCode etc)
I need to return the exact details back to System 1.
how will i do this?
1) I did try to add all codes in success codes 200..599, then even error is having 200 ok . This will cause more problem, because I have to add lot of choice routing as some flows are having more data conversion.
2) Ideal soln -> Raise exception as usual. This has to be caught in choice exception. Now I have to send the same status_code and the json response back to the caller.
Issue -? how can i find the payload returned by HTTP in exception object. Where is stored in exception object.

Here is the sample- one way of handling this kind of scenario , use validation Component to throw exception and capture in your mainflow either by exceptionHandling or by APIKIT ExceptionHandling
<flow name="routeexceptionFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" doc:name="HTTP"/>
<logger level="INFO" doc:name="Logger"/>
<http:request config-ref="HTTP_Request_Configuration" path="/in" method="POST" doc:name="HTTP">
<http:success-status-code-validator values="200..599"/>
</http:request>
<validation:is-false config-ref="Validation_Configuration" message="#[payload]" exceptionClass="nz.co.exception.BadRequestException" expression="#[message.inboundProperties['http.status'] ==400]" doc:name="Validate Bad Request"/>
<validation:is-false config-ref="Validation_Configuration" message="#[payload]" expression="#[message.inboundProperties['http.status'] !=200]" doc:name="Capture all other Exceptions"/>
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="#[exception.causeMatches('nz.co.exception.BadRequestException')]" doc:name="Catch Exception Strategy">
<set-payload value="#[exception.message]" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="****log all other exception****" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
</flow>
Add this class in your java folder
package nz.co.exception;
public class BadRequestException extends Exception {
private static final long serialVersionUID = 8546839078847602529L;
public BadRequestException() {
super();
}
public BadRequestException(String message) {
super(message);
}
public BadRequestException(Throwable t) {
super(t);
}
public BadRequestException(String message, Throwable t) {
super(message, t);
}
}
In your project if you are using APIKIT Router , then instead of using exceptionHandling as above, add directly nz.co.exception.BadRequestException in 400 ReturnCode apikitExceptionHandling.

Related

Mule Soft Data Weave

I want to write a Data Weave Code wherein if the data is null then it should route to 400. How do I write this in Mule Soft?
My flow is as follows:
HTTP -->Transfomer-->Logger
Tranformer DW code
{
event_ops_type: payload.EDM_generic_consumer_message.event_meta_data.event_operation_type
}
Now what I want to implement is if "event_ops_type" is null then route to 400(Exception Handling)?
You may want to try using a validation module. MuleSoft documentation here.
<validation:is-not-null message="event_ops_type is null!" value="#[flowVars.event_ops_type]" exceptionClass="com.example.MyException" doc:name="Validation"/>
You can also use a Groovy script in a choice block to throw any exception you'd like. Here, it will actually throw a 404 with the API generated exception handling. You could switch this to any exception you'd like.
<choice doc:name="Choice">
<when expression="#[flowVars.event_ops_type != null]">
<logger message="#[flowVars.event_ops_type]" level="INFO" doc:name="Logger"/>
</when>
<otherwise>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[throw new org.mule.module.apikit.exception.NotFoundException(flowVars['event_ops_type'] + " is null!"); ]]></scripting:script>
</scripting:component>
</otherwise>
</choice>
<exception-strategy ref="api-apiKitGlobalExceptionMapping" doc:name="Reference Exception Strategy"/>
You can use choice router after transformer to check payload.event_ops_type == "400". Then either raise custom exception for exception handling or set response status and reason based on event_ops_type 400.

mule mapping-exception-strategy only falls through to first 401 branch

asking this for some mulesoft expertise.
the following exception mapping strategy is supposed to branch on hhtp.status 401, 403, 429 but keeps on falling into the 401 branch for status codes 401 and 403 (at least, and determined by both debugging and log written to console):
<apikit:mapping-exception-strategy doc:name="waysact-adaptor-main-exception-strategy">
<apikit:mapping statusCode="401">
<apikit:exception value="org.mule.module.http.internal.request.ResponseValidatorException"/>
<logger message="psc>>> logging 401 = #[payload]" level="INFO" doc:name="log-http-401"/>
</apikit:mapping>
<apikit:mapping statusCode="403">
<apikit:exception value="org.mule.module.http.internal.request.ResponseValidatorException"/>
<logger message="psc>>> logging 403 = #[payload]" level="INFO" doc:name="log-http-403"/>
</apikit:mapping>
<apikit:mapping statusCode="429">
<apikit:exception value="org.mule.module.http.internal.request.ResponseValidatorException"/>
<logger message="psc>>> logging 429 = #[payload]" level="INFO" doc:name="log-http-429"/>
</apikit:mapping>
<apikit:mapping statusCode="400">
<apikit:exception value="org.mule.module.http.internal.request.ResponseValidatorException"/>
<logger message="psc>>> logging anything = #[payload]" level="INFO" doc:name="logging-anything"/>
</apikit:mapping>
</apikit:mapping-exception-strategy>
is this because it is branching only on exception type org.mule.module.http.internal.request.ResponseValidatorException? i thought it was meant to branch on the status code?
there is another strategy, choice-exception-strategy, that should branch on different exception object types.
Branching of exception based on http.status can be defined with choice exception strategy as below example,
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="#[message.inboundProperties.'http.status'=='404']" doc:name="Catch Exception Strategy" >
<logger message="Exceptions message is ... #[exception.message]" level="ERROR" doc:name="exceptionLogger"/>
<set-variable variableName="exceptionMessage" value="#[exception.message]" doc:name="Set exceptionMessage"/>
<set-payload value="{ errors: { errorCode: #[message.inboundProperties.'http.status'], errorMessage: #[flowVars.exceptionMessage] } }" doc:name="Set Exception Payload"/>
</catch-exception-strategy>
<catch-exception-strategy doc:name="Catch Exception Strategy" >
<logger message="Exception message is ... #[exception.message]" level="ERROR" category="com.project.stacktrace" doc:name="exceptionLogger"/>
<set-variable variableName="exceptionMessage" value="#[exception.message]" doc:name="Set exceptionMessage"/>
<set-payload value="{ errors: { errorCode: #[message.inboundProperties.'http.status'], errorMessage: #[flowVars.exceptionMessage] } }" doc:name="Set Exception Payload"/>
</catch-exception-strategy>
</choice-exception-strategy>
APIkit matches the exception based on the exception value defined and not by the statusCode defined. Use choice exception strategy and define multiple catch exception strategy in it. Make sure each catch exception strategy matches a unique exception to make the way for proper http.status code and desired exception payload.
For example, if you want to have 400 to be thrown, make sure a catch exception strategy matches BadrequestException. If the status codes are coming out of the HTTP requester, match the ResponseValidatorException and set the incoming http.status and exception payload

Mule Rest exception handling

Mule Flows:
<jersey:resources doc:name="REST">
<component class="com.test.qb.rest.MapIIFContent"/>
<jersey:exception-mapper class="com.test.qb.exception.IIFExceptionMapper" />
</jersey:resources>
<catch-exception-strategy doc:name="Audit Exception" >
<set-variable variableName="status" value="Failure" doc:name="Status"/>
<flow-ref name="QB:audit" doc:name="audit"/>
<http:response-builder status="500" contentType="application/json" doc:name="Status Code"/>
</catch-exception-strategy>
<logger message=" ===Reached here====" level="INFO" doc:name="Logger"/> <!-- Line 10-->
Java Rest component:
Rest Component:
try{
String s =null;
s.toString();// throw nullpointer exception
} catch (IIFException e) {
return Response.status(500).entity(e.getMessage()).type("Application/json").build();
}
return Response.ok(res).build();
When I run this, it goes to catch block in Java Rest component with error status as 500.
But in Mule flows i am expecting flow should reach
'catch-exception-strategy doc:name="Audit Exception" >
block, but it doesn't reach there, instead it reaches to line 10. How do I handle this?
I made rest component to throw checked custom exception instead of returning Rest Response status:
try{
String s =null;
s.toString();
} catch (IIFException e) {
throw new IIFException(e.toString(),e.getCause());
}
return Response.ok(res).build();
And in my exception flows, made it as:
<catch-exception-strategy doc:name="Audit Exception" >
<expression-component doc:name="Create error response"><![CDATA[#[payload = "{\"status\":\"error\", \"message\":\"" + exception.cause.message + "\"}"]]]></expression-component>
<http:response-builder status="500" contentType="application/json" doc:name="Status Code"/>
</catch-exception-strategy>

Scatter gather routing error. Message payload is of type: String

I'm new to Mule and while working on a fairly simple Hello World example on Anypoint Studio to test out the Scatter/Gather flow control element, I'm getting the following error, without much else in the way of information:
ERROR 2014-12-19 22:00:30,172 [[unifinesb].connector.http.mule.default.receiver.02] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : Exception was found for route(s): 0. Message payload is of type: String
Type : org.mule.routing.CompositeRoutingException
Code : MULE_ERROR--2
JavaDoc : http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/routing/CompositeRoutingException.html
Payload : /Waldo
********************************************************************************
Exception stack is:
1. Exception was found for route(s): 0. Message payload is of type: String (org.mule.routing.CompositeRoutingException)
org.mule.routing.CollectAllAggregationStrategy:51 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/routing/CompositeRoutingException.html)
********************************************************************************
Root Exception stack trace:
org.mule.routing.CompositeRoutingException: Exception was found for route(s): 0. Message payload is of type: String
at org.mule.routing.CollectAllAggregationStrategy.aggregateWithFailedRoutes(CollectAllAggregationStrategy.java:51)
at org.mule.routing.CollectAllAggregationStrategy.aggregate(CollectAllAggregationStrategy.java:38)
at org.mule.routing.ScatterGatherRouter.processResponses(ScatterGatherRouter.java:207)
at org.mule.routing.ScatterGatherRouter.process(ScatterGatherRouter.java:135)
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.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:24)
at org.mule.execution.MessageProcessorExecutionTemplate.execute(MessageProcessorExecutionTemplate.java:44)
at ...
Judging from the top description of the error, I understand the problem to be that Scatter gather does not receive String payloads, even though the current documentation for the component mentions nothing of the sort. Is this correct?
The flow I'm running is fairly simple, receiving a String from an inbound http and trying to route it to a REST service that will use the String to print something (returning text/plain) and to a DB to store the String in a table. Relevant code follows:
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8084" doc:name="HTTP"/>
<expression-filter expression="#[payload != '/favicon.ico']" doc:name="Filter browser icon padding"/>
<logger message="current payload is #[payload]" level="INFO" doc:name="Startup log - to stdout"/>
<scatter-gather doc:name="Scatter-Gather">
<processor-chain>
<logger message="#['Rest branch msg input :' + payload]" level="DEBUG" doc:name="File Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:8080/application/rest/mensaje?givenName=#[payload]" doc:name="REST Service"/>
<logger message="#['Rest msg output :' + payload]" level="DEBUG" doc:name="File Logger"/>
</processor-chain>
<processor-chain>
<logger message="#['Database msg input :' + payload]" level="DEBUG" doc:name="File Logger"/>
<db:insert config-ref="MySQL_VestaLocal" doc:name="Application Postgress">
<db:parameterized-query><![CDATA[insert into http_user_info (first_name) values ('#[payload]');]]></db:parameterized-query>
</db:insert>
<logger message="#['Database msg output :' + payload]" level="DEBUG" doc:name="File Logger"/>
</processor-chain>
</scatter-gather>
<set-payload value="#['REST DB Success!']" doc:name="Set Payload"/>
Trawling through the net I found this old Mule JIRA issue with an exception similar to what I'm getting, but trying out the suggested solution (workaround?) didn't do anything for me: https://www.mulesoft.org/jira/browse/MULE-7594
Something wrong is happening in your route 0.
You are getting a composite routing exception as per documentation:
The CompositeRoutingException is new to the 3.5.0 Runtime. It extends
the Mule MessagingException to aggregate exceptions from different
routes in the context of a single message router. Exceptions are
correlated to each route through a sequential ID.
This exception exposes two methods which allow you to obtain the IDs
of failed routes and the exceptions returned by each route.
The getExceptions method returns a map where the key is an integer
that identifies the index of the failed route, and the value is the
exception itself. The getExceptionForRouteIndex(int) method returns
the exception of the requested route ID.
As you don't have an execption strategy, the toString is call to that exception and that only prints the route failing (that has nothing to do with the fact that the payload is String)
Please use the following exeption strategy to find out exactly what's wrong:
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger level="ERROR" message="#[exception.exceptions]"/>
</catch-exception-strategy>

Mule: No Receiver registered error during Functional Test case run

I was trying to develop a Functional Test case for my mule configuration. Here is the code:
protected String getConfigResources() {
// TODO Auto-generated method stub
return "src/test/resources/employee-get-functionalTestCase-config.xml";
}
#Test
public void testMessage() throws Exception {
MuleClient client = muleContext.getClient();
client.dispatch("vm://in", "70009", null);
MuleMessage result = client.request("vm://out", 60000);
Assert.assertNotNull("Response payload was null", result);
Assert.assertNull(result.getExceptionPayload());
Assert.assertFalse(result.getPayload() instanceof NullPayload);
& here is the context of my XMl file:
<spring:beans>
<context:property-placeholder location="classpath:mule-app.properties"/>
</spring:beans>
<flow name="testFlow">
<vm:inbound-endpoint path="in"/>
<logger message="in functional-test-config.xml (v4)" level="INFO" doc:name="Logger"/>
<set-payload value="70010" doc:name="Use fixed employeeId 70010"/>
<vm:outbound-endpoint exchange-pattern="request-response" path="employee-profile-get" doc:name="VM"/>
<logger message="after employee-profile-get; payload: #[payload]" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint path="out"/>
</flow>
However when I execute this code, I get the following error:
org.mule.api.transport.NoReceiverForEndpointException: There is no receiver registered on connector "connector.VM.mule.default" for endpointUri vm://employee-profile-get
Where do I register the vm endpoint?
You must have an inbound endpoint for every exchange-pattern="request-response" vm endpoint .
When the application is run in your mule studio you may not get any error(at compile time ) but when the message is passed through the flow you will get an error of the above mentioned sort .
This is because VM is an in-memory queue ,where once you put a message, there should be a receiver to pick the message thus when not there this error pops and it is only for the exchange-pattern="request-response" because the flow from where you put the message(outbound endpoint with request-response) will wait for a response from the vm endpoint "employee-profile-get" .
To depict the same error replace the with a localhost http endpoint and try invoking the http endpoint .
To avoid this create another flow with inbound endpoint as vm with path="employee-profile-get" and return a string using set payload component .Then your test case would work.
Regards,
Naveen Raj