Scenario - I have to iterate over this payload, and for those listings with error I would need to increment count. But how to check if error property exists?
{
"jobGuid": "123",
"status": "COMPLETED",
"listings": [
{
"exteralListingId": 7654320
},
{
"exteralListingId": 7654321,
"error": {
"code": "inventory.listings.sellerCreditCardNotfound",
"description": "Seller credit card not found"
}
}
]
}
Option1 - Check using json syntax
Option2 - Iterating in a for-each loop over listings, checked for #[payload.error !=null]. But it gave error - Message payload is of type: LinkedHashMap
You can use jsonPath something like xpath but for JSON
I attached my example with the json provided. As you can see there are #[json:listings] which return array, this array will be iterated by foreach and then validate if contains error tag using #[json:error]. errorCount variable store the number of errors and it will be printed in the console.
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="demoFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<set-payload value="{"jobGuid":"123","status":"COMPLETED","listings":[{"exteralListingId":7654320},{"exteralListingId":7654321,"error":{"code":"inventory.listings.sellerCreditCardNotfound","description":"Seller credit card not found"}},{"exteralListingId":7654321,"error":{"code":"inventory.listings.sellerCreditCardNotfound","description":"Seller credit card not found"}},{"exteralListingId":7654321,"error":{"code":"inventory.listings.sellerCreditCardNotfound","description":"Seller credit card not found"}}]}" doc:name="Set Payload"/>
<expression-transformer expression="#[json:listings]" doc:name="Expression"/>
<set-variable variableName="errorCount" value="#[0]" doc:name="Variable"/>
<foreach collection="#[message.payload]" doc:name="For Each">
<expression-filter expression="#[json:error]" doc:name="Expression"/>
<set-variable variableName="errorCount" value="#[flowVars.errorCount + 1 ]" doc:name="Variable"/>
<logger message="counter: #[errorCount]" level="INFO" doc:name="Logger"/>
</foreach>
</flow>
For more information check the official documentation at mule .
http://www.mulesoft.org/documentation/display/current/JSON+Module+Reference
Related
While using MULE, I convert payload received from HTTP request to json object and mapped it to variables. In case, when I do not pass one of the variable, I get exceptions while evaluating the expression.
<flow name="test">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<json:json-to-object-transformer returnClass="java.lang.Object" doc:name="JSON to Object"/>
<set-variable variableName="a" value="#[message.payload.a]"
<set-variable variableName="b" value="#[message.payload.b]"
<logger message="a: #[a]" level="INFO" doc:name="Logger"></logger>
</flow>
When the payload is
{
"a": "val1",
"b": "val2"
}
The applications runs fine.
But if the payload is
{
"b": "val2"
}
I get the following exception:
ERROR [].HTTP_Listener_Configuration.worker.01] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : Execution of the expression "a" failed. (org.mule.api.expression.ExpressionRuntimeException).
Payload : {b="val2"}
Payload Type : java.util.LinkedHashMap
Element : /test/processors/10 # test:test.xml:47 (Logger)
Element XML : <logger message="a: #[a]" level="INFO" doc:name="Logger"></logger>
--------------------------------------------------------------------------------
Root Exception stack trace:
[Error: unresolvable property or identifier: a]
[Near : {... a ....}]
Can I check and append the value of variable 'a' as NULL ?
P.S. I would like to use this variable for sending as one of the parameters in payload for some other http request.
using #[flowVars.a] instead of #[a] will result in null instead of a exception.
Something is not right with your implementation. After the http listener, the payload is a raw response(JSON), which in any way cannot be access by #[payload.a] or #[payload['a']]. You should add an json to Object(which converts the json to map). From here you could reference it like this #[payload['a']] or #[payload.a]
I am trying to capture error status from one API & and send it to the calling API. In my downstream API I have the following catch exception strategy:
<catch-exception-strategy>
<set-payload value= "500" />
<logger message="***BACKEND API: #[payload]" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
In my calling API I have the following:
<http:request config-ref="downstream API " path="/downstream/{id}" method="POST " doc:name="Generate "/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<logger message="PAYLOAD: #[payload]" level="INFO" doc:name="Logger"/>
However I am able to print the payload in the downstream API but not in the calling API. Am I missing something?
If your API throw http.status == 500, it should trigger this condition
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="#[message.inboundProperties.'http.status' == 500]" doc:name="Error 500">
<set-payload value= "500" />
<logger message="***BACKEND API: #[payload]" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
I you didn't add any condition, it should be the default catch exception
everything should work properly.
I have a simple flow on AnyPointStudio that consumes a webservices and transforms it to JSON.
Im consuming a webservice that has the periodic table:
http://www.webservicex.net/periodictable.asmx?WSDL
However when using the getAtomicNumber service im getting the data of the xml as a string and the XML to JSON give this result:
{
"GetAtomicNumberResponse" : {
"#xmlns:xsd" : "http://www.w3.org/2001/XMLSchema",
"#xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
"#xmlns:xmlns" : "http://www.webserviceX.NET",
"GetAtomicNumberResult" : "<NewDataSet>\n <Table>\n <AtomicNumber>49</AtomicNumber>\n <ElementName>Indium</ElementName>\n <Symbol>In</Symbol>\n <AtomicWeight>114.82000000000001</AtomicWeight>\n <BoilingPoint>2300</BoilingPoint>\n <IonisationPotential>5.79</IonisationPotential>\n <EletroNegativity>1.49</EletroNegativity>\n <AtomicRadius>1.5</AtomicRadius>\n <MeltingPoint>430</MeltingPoint>\n <Density>7310</Density>\n </Table>\n</NewDataSet>"
}
}
As you can see it does not parse the GetAtomicNumberResult.
How can I get the entire result parsed as JSON?
The problem you are facing is because the soap response object has an embedded object with the element details. What you would do is, extract the response object and perform xml to json after that. See below:
<flow name="periodic_tableFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/table" doc:name="HTTP"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/xml
%namespace ns0 http://www.webserviceX.NET
---
{
ns0#GetAtomicNumber: {
ns0#ElementName: "Indium"
}
}]]></dw:set-payload>
</dw:transform-message>
<logger message="#[message.payloadAs(String)]" level="INFO" doc:name="Logger"/>
<ws:consumer config-ref="Web_Service_Consumer" operation="GetAtomicNumber" doc:name="Web Service Consumer"/>
<dw:transform-message metadata:id="021335ff-1e33-4cdd-be35-49d95f93b8bc" doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
%namespace ns0 http://www.webserviceX.NET
---
payload.ns0#GetAtomicNumberResponse.ns0#GetAtomicNumberResult]]></dw:set-payload>
</dw:transform-message>
<json:xml-to-json-transformer doc:name="XML to JSON"/>
<logger message="Before transformer - #[payload]" level="INFO" doc:name="Logger"/>
<echo-component doc:name="Echo"/>
</flow>
</mule>
I have a Mule config in which there is 2 flows :-
One flow expose a REST Service :-
<flow name="restServiceFlow1" doc:name="restFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" doc:name="HTTP"/>
<jersey:resources doc:name="REST">
<component class="com.test.services.schema.maindata.v1.Impl.MainDataImpl"/>
</jersey:resources>
</flow>
and another flow that consume the service by placing JSON request through file inbound :-
<flow name="restFlow2">
<file:inbound-endpoint path="E:\backup\test" responseTimeout="10000" connector-ref="File_Global">
<file:filename-regex-filter pattern="aa.txt" caseSensitive="false"/>
</file:inbound-endpoint>
<json:json-to-object-transformer returnClass="java.util.HashMap"/>
<foreach collection="#[payload.insertDataRequest]">
<http:outbound-endpoint exchange-pattern="request-response"
contentType="application/json" method="GET"
address="http://localhost:8082/getData/insert/?id=#[payload.id]&name=#[payload.name]&age=#[payload.age]&designation=#[payload.designation]"/>
</foreach>
</flow>
Now requirement to to check the content type after the file inbound endpoint whether the content type is JSON ... if the content Type is not equal to JSON then it will show not JSON message in log ..
I have tried the following :-
I placed a choice router after File inbound endpoint :-
<when evaluator="groovy" expression="payload.ContentType=='JSON'">
to check the content type the payload and if the content type is not JSON it will show not JSON in log and so I placed the log in Default of choice router ... But I am getting following exception :-
Exception stack is:
1. No such property: ContentType for class: org.mule.transport.file.ReceiverFileInputStream (groovy.lang.MissingPropertyException)
org.codehaus.groovy.runtime.ScriptBytecodeAdapter:50 (null)
2. groovy.lang.MissingPropertyException: No such property: ContentType for class: org.mule.transport.file.ReceiverFileInputStream (javax.script.ScriptException)
org.codehaus.groovy.jsr223.GroovyScriptEngineImpl:323 (http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/script/ScriptException.html)
Now is there any better way to check the content type after file inbound endpoint ??? please suggest some better way ...Please note I don't want to use is-json-filter because I want to control the else condition and display message in log ...
You can still use the is-json-filter but you need to wrap it in a message filter so you can control the "else" path:
<message-filter onUnaccepted="noJsonFlow" throwOnUnaccepted="false">
<json:is-json-filter />
</message-filter>
First, thank you for the amazing job you guys are doing. I'm spending more and more time on your site, and this is my first help request.
I'm evaluating mule esb.
i'm trying to iterate a json array to dispatch to different queues according to, for instance, the attribute "activity".
{
"activitylist":[
{
"activity": {
"serviceConsumer":"channelrecord",
"project":"5004channel 500448319610 type=",
"activity":"Transcodage",
"serviceProvider":"Internal"
}
},
{
"activity":{
"serviceConsumer":"channelrecord",
"project":"5004channel 500448319610 type=",
"activity":"Doublage",
"serviceProvider":"DubbingBroz"
}
}
]
}
i wrote a simple test flow to capture the json msg and trying to use foreach:
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" doc:name="activity/delegate/savelist" path="activity/delegate/savelist"/>
<foreach doc:name="For Each" collection="#[payload.activitylist]">
<logger message="#[payload.serviceConsumer]" level="INFO" doc:name="Logger"/>
</foreach>
but no luck. I'm getting these errors:
ERROR 2014-06-12 17:40:34,723 [[verto].connector.http.mule.default.receiver.02] org.mule.exception.DefaultMessagingExceptionStrategy:********************************************************************************
Message : Execution of the expression "payload.activitylist" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: ContentLengthInputStream
Code : MULE_ERROR--2 --------------------------------------------------------------------------------
Exception stack is:
1. [Error: could not access: activitylist; in class: org.apache.commons.httpclient.ContentLengthInputStream] [Near : {... payload.activitylist ....}]
[Line: 1, Column: 1] (org.mvel2.PropertyAccessException) org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer:690 (null)
2. Execution of the expression "payload.activitylist" failed (org.mule.api.expression.ExpressionRuntimeException) org.mule.el.mvel.MVELExpressionLanguage:213 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/expression/ExpressionRuntimeException.html)
3. Execution of the expression "payload.activitylist" failed (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: ContentLengthInputStream (org.mule.api.MessagingException) org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor:35 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)--------------------------------------------------------------------------------
any suggestion to help me to dispatch this stuff gracefully would be greatly appreciated.
Add the following between http:inbound-endpoint and forEach:
<json:json-to-object-transformer returnClass="java.lang.Object" />
Use splitter component as for the alternative and use json path to json string,
<splitter expression="#[json:activitylist]" doc:name="Splitter"/>
<logger message="Activity #[json:activity/serviceConsumer]" level="INFO" doc:name="Logger"/>