Im trying to write CSV within For-each loop in Mule 3.
Reading CSV file
Passing parameter to the API to get response
if no response, will write into another csv file. To maintain parameter value i set record variable before API calling and no matches, would write into CSV.
But CSV file not generating within For-each loop.
<foreach collection="#[payload.names]" doc:name="For Each">
<foreach collection="#[payload.names]" doc:name="For Each">
<batch:set-record-variable variableName="userName" value="#[payload.Name]" doc:name="Record Variable"/>
<http:request config-ref="HTTP_Request_Configuration" path="/users" method="GET" doc:name="Users">
<http:request-builder>
<http:query-param paramName="name" value="#[payload.Name]"/>
</http:request-builder>
</http:request>
<choice doc:name="Choice">
<when expression="#[payload.results.size()>0]">
<dw:transform-message doc:name="Transform Message" >
<dw:input-payload mimeType="application/java"/>
<dw:set-payload><![CDATA[%dw 1.0
%output application/csv
---
[payload]]]></dw:set-payload>
</dw:transform-message>
<set-payload value="#[recordVars.userName]" doc:name="Set Payload"/>
<file:outbound-endpoint responseTimeout="10000" doc:name="File" outputPattern="users.csv" path="C://output"/>
</otherwise>
</choice>
</foreach>
</foreach>
While request processing mule application giving following exception:-
javax.servlet.ServletException: Property mule.context not set on ServletContext.
the flow snippet is like below :-
<logger message="#[message.payloadAs(java.lang.String)]" level="INFO" doc:name="Logger"/>
<dw:transform-message doc:name="Transform Message" me
</dw:transform-message>
<logger message="#[message.payloadAs(java.lang.String)]" level="INFO" doc:name="Logger"/>
</flow>
We would like to use DB query inside mule cache scope.
Wants to store the output of DB query in cache to save DB query trip.
If the DB query doesn't give any output or payload is empty, we dont want to save in mule cache.
How to invalidate the cache of the empty payload entries ?
thank you.
The answer to this is in mule forum, https://forums.mulesoft.com/questions/84675/mule-cache-scope-how-to-invalidate-mule-cache-for.html
<ee:cache cachingStrategy-ref="Caching_Strategy" filterExpression="#
[payload
!= 'testData']" doc:name="Cache">
<db:select config-ref="DBConfig" fetchSize="100"
doc:name="Database">
<db:dynamic-query><![CDATA[select * from STUDENT where
student_id = 'TEST']]></db:dynamic-query>
</db:select>
<choice doc:name="Choice">
<when expression="#[message.payload.size() == 0]">
<logger message="Payload is empty" level="INFO"
doc:name="Logger"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
payload]]></dw:set-payload>
</dw:transform-message>
</when>
<otherwise>
<object-to-string-transformer doc:name="Object to String"/>
</otherwise>
</choice>
<logger message="After Choice" level="INFO" doc:name="Logger"/>
</ee:cache>
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
We want to process all of the exceptions we catch with the same process in our exception strategy. It is the one generated by apikit. We first send a lot with a custom component and then we generate json response. In the response with DataWeave we want to set the same statusCode. However, the statusCode do not seem to be a variable that is retrievable. Am I correct, or there is a good way to retrieve it?
<apikit:mapping-exception-strategy xmlns:apikit="http://www.mulesoft.org/schema/mule/apikit" name="svc0031_hotel-apiKitGlobalExceptionMapping">
<apikit:mapping statusCode="504">
<apikit:exception value="org.mule.api.transformer.TransformerMessagingException"/>
<flow-ref name="svc0031_manageErrors" doc:name="Manage Error"/>
</apikit:mapping>
<apikit:mapping statusCode="404">
<apikit:exception value="org.mule.api.transformer.TransformerMessagingException"/>
<flow-ref name="svc0031_manageErrors" doc:name="Manage Error"/>
</apikit:mapping>
</apikit:mapping-exception-strategy>
<sub-flow name="svc0031_manageErrors">
<set-payload value="#[groovy:message.exceptionPayload.rootException.message]" doc:name="Set BIP Payload"/>
<custom-transformer class="se.zystems.baseline.BaselineLogging" doc:name="Log BIP Outgoing">
<spring:property name="Level" value="ERROR"/>
<spring:property name="ObjectId" value="CatchErrors"/>
<spring:property name="TransactionStatus" value="failed"/>
</custom-transformer>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
status : 400,
message : payload,
code : 42,
more_info :"https://anypoint.mulesoft.com/apiplatform/nordic-choice-hotels"
}]]></dw:set-payload>
</dw:transform-message>
<logger level="INFO" doc:name="Logger"/>
</sub-flow>
Good,
If you create a variable with the http.status then you can use it in the mapper:
<flow name="test">
<set-variable variableName="httpStatus" value="#[message.inboundProperties['http.status']" doc:name="Variable"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
status : flowVars.httpStatus,
message : payload,
code : 42,
more_info :"https://anypoint.mulesoft.com/apiplatform/nordic-choice-hotels"
}]]></dw:set-payload>
</dw:transform-message>
</flow>
I found out where the statusCode value is stored thanks to the answer by Jesús Pablo Fernández
He was almost right in his answer, however, the statusCode is stored not in message.inboundProperties['http.status'], but in message.outboundProperties['http.status']. No need to even extract a variable, one can just access it in data transformer directly like this:
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
status : outboundProperties['http.status'],
message : payload,
code : 42,
more_info :"https://anypoint.mulesoft.com/apiplatform/nordic-choice-hotels"
}]]></dw:set-payload>
</dw:transform-message>
Status codes defined in the APIKitExceptionStrategy will be those sent back in the response header as http.status given the corresponding exception to be raised.
For instance,
<apikit:mapping statusCode="504">
<apikit:exception value="org.mule.api.transformer.TransformerMessagingException"/>
<flow-ref name="svc0031_manageErrors" doc:name="Manage Error"/>
</apikit:mapping>
means that when a org.mule.api.transformer.TransformerMessagingException exception is thrown and caught by this exception block, then a 504 status code is sent back as a response header.
If you want to bypass the statusCode attribute in the APIKit exception block, you should have another exceptionStrategy block to catch your desired exception, and then you could set your status code like that
<set-property name="http.status" value="<the_desired_status, e.g. 401>" />
Hope it helps.
/Tony
Good Stanislav Ivanov,
I have a flow implemented with the APIKit, which is the code that I attach and whether there is property in the inboundProperties http.status, review it because if it should contain the value, if you do not have your flow may modify the value in a previous step.
I pointed him to directly access the outboundProperties in the mapper, I was not aware, thank you very much.