I am trying to throw a Filter Unaccepted Exception in munit to test my error handling but I am getting this error
org.mule.api.MessagingException: Failed to invoke throw-an.
at get_data_filter_unaccepted_exception-test.mock:throw-an{doc:name=Throw unaccepted Exception, exception-ref=#[new org.mule.api.routing.filter.FilterUnacceptedException()], whenCalling=.*:.*}(get_data_from_qcfc-test-suite.xml:316)
at appleFlow.munit:test{initialState=started, description=Test, ignore=false, abstract=false, id=MunitTestFlow$$EnhancerByMUNIT$$904837f0{get_data_filter_unaccepted_exception-test}}(get_data_from_qcfc-test-suite.xml:315)
Caused by: org.mule.api.expression.ExpressionRuntimeException: Execution of the expression "new org.mule.api.routing.filter.FilterUnacceptedException()" failed.
at org.mule.el.mvel.MVELExpressionLanguage.evaluateInternal(MVELExpressionLanguage.java:232)
This is my throw an exception
<mock:when messageProcessor=".*:.*" doc:name="Mock API Token Web Service Call">
<mock:with-attributes>
<mock:with-attribute name="doc:name" whereValue="#['Get API Token']"/>
</mock:with-attributes>
<mock:then-return payload="#[getResource('api_token_success.xml').asString()]" mimeType="application/xml"/>
</mock:when>
I think it is because of my MEL statement
#[new org.mule.api.routing.filter.FilterUnacceptedException()]
You could use a groovy component to throw your exception like that
<scripting:component doc:name="Throw Exception">
<scripting:script engine="Groovy"><![CDATA[throw new org.mule.api.routing.filter.FilterUnacceptedException(); ]]></scripting:script>
</scripting:component>
Hope it helps.
/T
I don't see throw-an call in the snippet you pasted.
Anyways, No argument constructor for org.mule.api.routing.filter.FilterUnacceptedException is not public, try using #[new org.mule.api.routing.filter.FilterUnacceptedException('Some message')]
Related
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.
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 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.
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!
There is flow which is going to call http-outbound endpoint. I want to write test case for the scenario if http is not available(catching the exception in flow and working as expected from POSTMAN). I tried using throw an exception for mocking the exception to be thrown when message process is http:request.. but it didn't worked. Can someone please help how to mock exception in munit?
Below is the code which i tried:
<munit:test name="test-project-test-suite-munit-testFlowTest3" description="Test" >
<mock:when messageProcessor="mule:set-payload" doc:name="Mock">
<mock:with-attributes>
<mock:with-attribute name="doc:name" whereValue="#['Set Payload']"/>
</mock:with-attributes>
<mock:then-return payload="#['payload3']"/>
</mock:when>
<mock:when messageProcessor="mule:flow" doc:name="Mock">
<mock:with-attributes>
<mock:with-attribute name="name" whereValue="#[matchContains('munit-testFlow2')]"/>
</mock:with-attributes>
<mock:then-return payload="#[]">
<mock:invocation-properties>
<mock:invocation-property key="variable2" value="#['response2']"/>
</mock:invocation-properties>
</mock:then-return>
</mock:when>
<mock:throw-an exception-ref="#[new org.mule.api.MessagingException()]" whenCalling="http:request" doc:name="Throw an Exception">
<mock:with-attributes>
<mock:with-attribute name="doc:name" whereValue="#['HTTP-RES']"/>
</mock:with-attributes>
</mock:throw-an>
<flow-ref name="munit-testFlow" doc:name="munit-testFlow"/>
<munit:assert-payload-equals message="oops failed" expectedValue="#['error-response']" doc:name="Assert Payload"/>
</munit:test>
Instead of using new org.mule.api.MessagingException() use like below
new IllegalArgumentException('messaging exception') or
new java.lang.Exception("messaging exception")
org.mule.api.MessagingException() is a protected function might not able to use in the way may be. Actually it comes under org.mule.api.MuleException() which is again protected.
https://www.mulesoft.org/docs/site/3.3.0/apidocs/org/mule/api/MessagingException.html
Please refer the below url for more details.
https://forums.mulesoft.com/questions/44929/munit-throw-exception-mock-not-working.html
working code
<munit:test name="sample-test-suite-sampleFlowTest" description="Test">
<mock:throw-an exception-ref="#[new java.lang.Exception('messaging exception')]" whenCalling="http:request" doc:name="Throw an Exception">
</mock:throw-an>
<flow-ref name="sampleFlow" doc:name="sampleFlow"/>
<logger level="INFO" doc:name="Logger"/>
</munit:test>