From the Main api, i call a subflow. I have defined error handler in the main flow and subflow.(mine is complex scenario)
Here is a simple flow design of what I'm trying;
From the main flow, within Async scope I call i subflow. Mainflow, itself has errorhandler.
Within reporting subflow, i call another subflow, which throws an 403 error.
I thought to handle that in reporting subflow. So i used, on error continue. I used log mediator there to see it gets executed or not.
But it is not.
Rather, from the main flow I get,log ' in main error handler'
I haven't defined any global error handlers.
Why is that?
Main flow
<flow name="post:\notifications:raml-config">
.................
<async doc:name="Async">
<try doc:name="Try">
<flow-ref doc:name="Call-Reporting-subFlow
name="reporting-subflow" />
<error-handler >
<on-error-propagate enableNotifications="true" logException="true" doc:name="On Error Propagate" doc:id="743fc7cb-38d4-4a0c-ab36-9105645ce710" >
<logger level="INFO" doc:name="Logger" doc:id="5d18eb33-780e-4353-b65f-b26eec88612a" message="in main errror handler"/>
............
</flow>
Subflow (reporting flow)
<sub-flow name-"reporting-subflow">
<try doc:name="Try" >
<flow-ref doc:name="getcontracts" name="get-details-subflow" />
<error-handler >
<on-error-continue enableNotifications="true" logException="true" doc:name="On Error Continue" type="HTTP:FORBIDDEN">
<logger level="INFO" doc:name="Logger" message="GOT 403 error"/>
<flow-ref doc:name="gettoken" name="getToken-subflow" />
</error-handler>
</try>
</sub-flow>
One of the below may be the reason:
We cannot define an error handling for a sub flow, we can do it only
for private flows and normal flows.
Even if the main flow has an error handler, the flow referred within
the Async scope will not be managed by this error handler. To solve
this:
make the flow referenced within the async error handler as a
private flow and define a error handling at flow level
or define global error handling at application level.
Related
A little description of the flow: I have a flow that is making an HTTP call to a REST Webservice. There are a couple of errors that we get as statusCode=500 but with different "errorCodes" inside the response body. This request connector is wrapped inside a try block with multiple on-error-continue based on the content of the response body in its "when" attribute. eg: error.errorMessage.payload.errorCode==CODE_A. Adding an image and source code of the flow below
<?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="dee432d7-a176-448c-a1ac-a374a86fa85b" >
<http:listener-connection host="0.0.0.0" port="8081" />
</http:listener-config>
<flow name="test2Flow" doc:id="be602af1-cfcf-46f1-a312-ea6a5544503b" >
<http:listener doc:name="Listener" doc:id="f160fa61-15be-4744-b823-973e20740e73" config-ref="HTTP_Listener_config" path="/test"/>
<logger level="INFO" doc:name="Some logic before request" doc:id="6354a117-e918-4937-a1d9-df4ae0ef6386" message="Some logic before request"/>
<try doc:name="Try" doc:id="15bd106a-c116-4d87-958e-8ad698026739" >
<http:request method="GET" doc:name="Request" doc:id="a046919e-f149-45d6-9a70-db37cac0540f" url="http://example.com/some-resource" />
<error-handler >
<on-error-continue enableNotifications="true" logException="true" doc:name="when error.errorMessage.payload.errorCode==CODE_A" doc:id="20fc0575-da65-41b4-81f7-d364227b1639" when='error.errorMessage.payload.errorCode=="CODE_A"'>
<logger level="INFO" doc:name="Some logic for CODE_A" doc:id="a699ccd0-952c-415f-b288-4ea027f2cff2" message="Some logic for CODE_A" />
</on-error-continue>
<on-error-continue enableNotifications="false" logException="false" doc:name="when error.errorMessage.payload.errorCode==CODE_B" doc:id="63dc8aa5-5fae-4235-a4ae-a80903a76362" when='error.errorMessage.payload.errorCode=="CODE_B"' >
<logger level="INFO" doc:name="Some logic for CODE_B" doc:id="9364ff1e-4bcd-48d5-a37a-a207828cda9d" message="Some logic for CODE_B" />
</on-error-continue>
</error-handler>
</try>
<logger level="INFO" doc:name="Some logic After request" doc:id="fd754198-d6b5-40dd-b23f-c8619faee7e6" message="Some logic After request" />
</flow>
</mule>
What I am trying to do: I am trying to write MUnit to verify if the correct error-handler block is executed based on response. However, I do not see any option to mock an error with its errorMessage part filled.
What I am looking for: I am trying to find out one of these
Anyway to mock error with errorMessage using the simple mock-when'sthen-return element. I do not think it is possible, but if there is a way please let me know.
Maybe there is a way to use a Java class for raising complex errors. I am thinking if I can use mock-when'sthen-call to call a flow and then raise an error using it.
Any other way to do it.
Note:
Mule version: 4.3.0 MUnit version: 2.3.0
I can not make change in the REST webservice, I do not own that.
I am trying to avoid any code change, For example, I can ignore status code in the message validator and do the error handling using response directly, with something like choice. But I will do it as the last resort
You can try using something like this when mocking error for HTTP requests:
Create the following DW file:
httpError.dwl
var detailMessage = 'Internal server error'
var myJsonResponse = '{"errorCode":"ERROR_A"}'
var typedValue = java!org::mule::runtime::api::metadata::TypedValue::new(myJsonResponse, java!org::mule::runtime::api::metadata::DataType::JSON_STRING)
var errorMessage = java!org::mule::runtime::api::message::Message::of(typedValue)
var errorType = java!org::mule::extension::http::api::error::HttpError::INTERNAL_SERVER_ERROR
---
java!org::mule::extension::http::api::request::validator::ResponseValidatorTypedException::new(detailMessage, errorType, errorMessage)
In your MUnit test suite file, create the following flow:
<flow name="munit-set-error-code-event-flow" doc:id="3b7e266c-2f3b-4105-8fdb-8ea44d5f128e" >
<munit:set-event doc:name="Generate error" doc:id="4ee8b870-6c8b-4570-bc70-7ec0086a1bca" cloneOriginalEvent="true">
<munit:error id="HTTP:INTERNAL_SERVER_ERROR" exception="#[${file::httpError.dwl}]" />
</munit:set-event>
</flow>
And, finally, in your actual MUnit test flow, configure the then-call option to call the above flow. Eg:
<munit:test name="test-test-suite-testFlowTest" doc:id="5670a9cd-758a-4f2c-a55f-57b48a9f3b41" description="Test" timeOut="1200000">
<munit:behavior >
<munit-tools:mock-when doc:name="Mock when" doc:id="466fd55c-80b4-4e27-82ed-f561223a3b4f" processor="http:request">
<munit-tools:with-attributes >
<munit-tools:with-attribute whereValue="08c4fba6-ef4b-4006-bd7d-deb1fd0f5304" attributeName="doc:id" />
</munit-tools:with-attributes>
<munit-tools:then-call flow="munit-set-error-code-event-flow" />
</munit-tools:mock-when>
</munit:behavior>
<munit:execution >
<flow-ref doc:name="Flow-ref to testFlow" doc:id="c57b3265-b453-432c-88fd-db2df7125fdc" name="testFlow"/>
</munit:execution>
</munit:test>
Although I'm not sure if this is something recommended to do, it should work for what you want to achieve.
Let me know if it works.
I have to define a global exception handler and for each flow I have to define the same set of exceptions I want to use global exception handling in Mule 4 , I am following below steps , please suggest/help to configure exception handling globally .
Under Global Configuration Elements ->I clicked on "Click Create Configuration"
2 .I defined default Error Handler in it .
Please find enclosed the screenshot for it .
Thanks
You can share an error handler in the XML view. Just add a ref attribute to the error-handler attribute pointing to the name of the global error handler.
Note that it is also better to use the XML to share. Flow logic is not clear with just screenshots.
Example:
<flow name="myFlow1">
...
<error-handler ref="Error_Handler">
</error-handler>
</flow>
<flow name="myFlow2">
...
<error-handler ref="Error_Handler">
</error-handler>
</flow>
<error-handler name="Error_Handler">
<on-error-propagate type="ANY">
<logger level="ERROR" doc:name="Log the error" message="An error happened!" />
</on-error-propagate>
</error-handler>
I created a global exception strategy as below,
<choice-exception-strategy name="GlobalExceptionStrategy">
<catch-exception-strategy name="400:BadRequest" when="#[message.inboundProperties['http.status']=="400"]" doc:name="400:BadRequest">
<logger message="Caught error with code #[message.inboundProperties['http.status']] and reason #[message.inboundProperties['http.reason']] for query payload #[message.payloadAs(java.lang.String)]" level="ERROR" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
But why I am still getting the error like name attribute is required only on global exception strategy?
Error was in this line <catch-exception-strategy **name**="400:BadRequest" when="#[message.inboundProperties['http.status']=="400"]" doc:name="400:BadRequest">
Using doc:name in place of name works perfect!
Currently I have a flow that exposes a REST service with a string as input parameter . I am using a regex -filter to ensure the format parameter as follows :
<http:inbound-endpoint doc:name="HTTP"
connector-ref="ciuServiceHTTPConnector" ref="ciuServiceHTTPEndpoint"
exchange-pattern="request-response" />
<logger level="INFO" doc:name="Logger" message="epale1 #[payload]"/>
<regex-filter pattern="^/api/person/(V|E)[0-9]{8}$"
doc:name="Regex" />
<logger message="epale2 #[payload]" level="INFO" doc:name="Logger"/>
<jersey:resources doc:name="REST" >
<component class="...resource.CiudadanoResource"/>
</jersey:resources>
I need to send the customer a message "Invalid or missing parameter" . For this I use a choice-exception-strategy and catch-exception-strategy and then call a Subflow and perform http:response-builder.
How can I throw an exception(type) when the regex-filter do not match?. It is possible to incorporate this behavior or should I change my flow?
Thanks for your help;
Wrap it in a message-filter, like this:
<message-filter throwOnUnaccepted="true">
<regex-filter pattern="^/api/person/(V|E)[0-9]{8}$"
doc:name="Regex" />
</message-filter>
See the official documentation for further details:
Check the Throw On Unaccepted box to throw an exception if a message
or event is not handled. The default when not checked is to not throw
an exception.
I am trying to call an async private flow from a main synchronous flow like so:
<flow name="main" doc:name="main" processingStrategy="synchronous">
<poll frequency="10000">
<set-payload value="main"></set-payload>
</poll>
<flow-ref name="async-private" />
<flow-ref name="private" />
</flow>
<flow name="private" processingStrategy="synchronous">
<logger level="ERROR" message="sync" />
</flow>
<flow name="async-private" processingStrategy="asynchronous">
<logger level="ERROR" message="async" />
</flow>
But it does not work and results in the following exception:
Unable to process a synchronous event asynchronously. Message payload is of type: String (org.mule.api.MessagingException)
What is going on here?
UPDATE
It works if I wrap the async flow-ref in <async> tags. But why do I need to do this? Is it a bug?
This is a feature.
You are in an explicit synchronous flow and try to call an explicit asynchronous one. The response from the asynchronous flow will never make it back to the caller flow. Thus there is a potential for losing messages. Thus Mule forces you to be explicit and wrap with <async> tags.