How do you accumulate values within a ForEach loop in Mule? - json

I have the below json output:
{
"results": [
{
"ID": "1",
"ImageID": "2",
"Name": "Test1",
"Owner": "sysadmin",
"Author": "sysadmin",
"Creator": "sysadmin"
},
{
"ID": "2",
"ImageID": "23",
"Name": "Test2",
"Owner": "sysadmin",
"Author": "sysadmin",
"Creator": "sysadmin"
}
]
}
For each ID in above response, i need to invoke the rest service passing ID as a parameter and the rest service will send me a response back. I have to consolidate all the output into a single json response in mule.
I have tried using for each and enricher but could not able to build it. Below is the code which i am using.
<foreach doc:name="For Each Loop">
<logger level="INFO" message="#[payload]" doc:name="Logger" category="INFO"/>
<json:json-to-object-transformer doc:name="JSON to Object"/>
<enricher doc:name="Message Enricher">
<http:request config-ref="SAM" path="/abc/#[payload.ID]" method="GET" doc:name="HTTP"/>
<enrich target="#[flowVars.ID]" source="#[payload[0].ID]"/>
</enricher>
<logger level="INFO" message="#[flowVars.ID]" doc:name="Logger" />
<expression-component doc:name="Expression"><![CDATA[payload.ID = flowVars.ID; ]]></expression-component>
</foreach>
Kindly help me with the way to fix this !!
Thanks

You need to initialize an empty array before the for-each loop and add to that array within the for-each:
<set-variable variableName="idList" value="#[[]]" doc:name="Variable - Init idList"/>
<foreach doc:name="For Each Loop">
<logger level="INFO" message="#[payload]" doc:name="Logger" category="INFO"/>
<json:json-to-object-transformer doc:name="JSON to Object"/>
<enricher doc:name="Message Enricher">
<http:request config-ref="SAM" path="/abc/#[payload.ID]" method="GET" doc:name="HTTP"/>
<enrich target="#[flowVars.ID]" source="#[payload[0].ID]"/>
</enricher>
<logger level="INFO" message="#[flowVars.ID]" doc:name="Logger" />
<expression-component doc:name="Expression"><![CDATA[flowVars.idList.add(flowVars.ID);]]></expression-component>
</foreach>
I cover this topic in this video.

Thanks Jerney !!
I made it working by doing the following:
<set-variable variableName="outputList" value="#[new java.util.ArrayList()]" doc:name="SetEmptyArray"/>
<foreach collection="json:packshots" doc:name="ForEachDocument">
<set-variable variableName="docName" value="#[json:Name]" doc:name="docName"/>
<http:request config-ref="AH_DAM_API_Configuration" path="${ah.dam.api.get.renditions.path}#[json:Name]" method="GET" doc:name="InvokeAHDamService"/>
<set-payload value="#[xpath3('//*:service/*:document',payload,'NODE')]" doc:name="fetchRenditionInfo"/>
<expression-transformer expression="#[flowVars.outputList.add(payload)]" doc:name="AppendResponseToArray"/>
</foreach>

I have used from the savedOutput for array variable.

Related

Concatenate two JSON responses in wso2 esb

I have two json from two different endpoints, i need to concatenate to convert it into a single valid json. I did it, but the first WSO2 json returns it as a string (firstjson). I would like it to be all a json.
FIRST JSON
{
"first": true,
"second": {
"name": "manoj",
"age": "45"
},
"third": {
"fourth": [
{
"class": "test12",
"salary": "123456"
},
{
"class": "test23",
"salary": "15678"
}
],
"fifth": "hello"
}
}
SECOND JSON
[
{
"item1": "123456",
"item2": "5678"
},
{
"item1": "8976",
"item2": "abcd"
}
]
XML API
<api context="/concat" name="concat" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET" url-mapping="/concatenare">
<inSequence>
<call>
<endpoint>
<http method="get" uri-template="http://www.mocky.io/v2/56b2d88c13000057518945d4">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<enrich>
<source clone="false" type="body"/>
<target property="first-json" type="property"/>
</enrich>
<log level="custom">
<property expression="get-property('first-json')" name="First json"/>
</log>
<call>
<endpoint>
<http method="get" uri-template="http://www.mocky.io/v2/56b2d87d1300007c518945d3">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<log level="custom">
<property expression="get-property('first-json')" name="*********BEFOREEEEEEEE"/>
</log>
<!-- <enrich>
<source clone="false" property="first-json" type="property"/>
<target type="body"/>
</enrich> -->
<payloadFactory media-type="xml">
<format>
<completeJson xmlns="">
<firstjson>$1</firstjson>
<secondjson>$2</secondjson>
</completeJson>
</format>
<args>
<arg evaluator="xml" expression="get-property('first-json')"/>
<arg evaluator="xml" expression="$body"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<send/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
RESPONSE API
{
"completeJson": {
"firstjson": "{\"first\":true,\"second\":{\"name\":\"manoj\",\"age\":\"45\"},\"third\":{\"fourth\":[{\"class\":\"test12\",\"salary\":\"123456\"},{\"class\":\"test23\",\"salary\":\"15678\"}],\"fifth\":\"hello\"}}",
"secondjson": {
"Body": [
{
"item1": 123456,
"item2": 5678
},
{
"item1": 8976,
"item2": "abcd"
}
]
}
}
}
Where am I wrong ?
Thanks in advance guys
Ok guys,
I solved it, I was wrong with the payloadFactory, the format it had to be of type json.
<payloadFactory media-type="json">
<format>
{
"completeJson" : {
"firstjson" : $1,
"secondjson" : $2
}}
</format>
<args>
<arg expression="get-property('first-json')" />
<arg expression="$body" />
</args>
</payloadFactory>
thanks anyway guys :)

Replace value in Json in Dataweave

The mule payload is in flowVars (infodata)
[
{
"status": "submitted",
"identity": "",
"papers": {
"code1": "12csd3cbsdj",
"code2": "skd02nd28dn",
"date": "2016-06-22",
"party": {
"due_date": "2016-06-22",
"personel": {
"email": "tt#test.com",
"value": {
"amount": "0.10",
"inflation": "HIGH"
}
}
}
}
}
]
Inside Dataweave,
(1) how to remove the square brackets?
(2) how to replace the value of amount and inflation dynamically (from flowVars)?
Question 2:You can directly use flowVars inside dataweave or if the values are in url you can dynamically set values using inboundProperties. Refer: https://docs.mulesoft.com/mule-user-guide/v/3.7/dataweave-reference-documentation
I have used set variable where you can dynamically exact it.Test Url used in this flow: http://localhost:8083/test?inflation=HIGH
<flow name="testFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP">
</http:listener>
<logger level="INFO" doc:name="Logger"/>
<set-variable variableName="dynamicValueAmount" value="#['2']" doc:name="Variable"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
[
{
"status": "submitted",
"identity": "",
"papers": {
"party": {
"due_date": "2016-06-22",
"personel": {
"email": "tt#test.com",
"value": {
"amount": flowVars.dynamicValueAmount,
"inflation": inboundProperties.'http.query.params'.inflation
}}}}}
]]]></dw:set-payload>
</dw:transform-message>
<object-to-string-transformer doc:name="Object to String"/>
<set-payload value="#[ message.payload =org.mule.util.StringUtils.replace(message.payload,"[","{");message.payload =org.mule.util.StringUtils.replace(message.payload,"]","}")]" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
Regarding Question one, i have externally used replace function in set Payload( Working fine - other way). I believe it can be achieve in standard way by using Dataweave itself. Let wait for the answers.
I have resolved question #1
%dw 1.0
%output application/java
---
{
data:flowVars.infodata replace /(\[|\])/ with ""
}
I'm still trying to understand how to dynamically change the content of the payload for question #2.
Looking at the sample flowVar content, it looks like an array of json object. Is that correct? If it is array then inside dataweave, you can either iterate over flowVars.infodata map {} or just get the first object data: flowVars.infodata[0].
Not sure what you really mean by dynamically changing content. #star has shown a way how you can reference any variables inside your dataweave code. May be you can add some of your code that you are looking to edit?

How to concatenate two JSON responses in wso2 esb

The two jsons i need to concatenate to convert it into a single valid json are :
{
"first": true,
"second": {
"name": "manoj",
"age": "45"
},
"third": {
"fourth": [{
"class": "test12",
"salary": "123456"
},
{
"class": "test23",
"salary": "15678"
}
],
"fifth": "hello"
}
}
and
[{
"item1": "123456",
"item2": "5678"
},
{
"item1": "8976",
"item2": "abcd"
}]
Is it possible to concatenate these two without using any jquery. I need something related to wso2 esb code. I tried using enrich and other mediators but no luck so far.
You can concat the jsons using WSO2 ESB Payload Factory mediator as follows,
<api xmlns="http://ws.apache.org/ns/synapse" name="ConcatAPI" context="/concat">
<resource methods="GET">
<inSequence>
<call>
<endpoint>
<http method="GET" uri-template="http://www.mocky.io/v2/56b2d88c13000057518945d4"/>
</endpoint>
</call>
<enrich>
<source type="body" clone="true"/>
<target type="property" property="first-json"/>
</enrich>
<log level="custom">
<property name="First json" expression="get-property('first-json')"/>
</log>
<call>
<endpoint>
<http method="GET" uri-template="http://www.mocky.io/v2/56b2d87d1300007c518945d3"/>
</endpoint>
</call>
<payloadFactory media-type="xml">
<format>
<completeJson xmlns="">
<firstjson>$1</firstjson>
<secondjson>$2</secondjson>
</completeJson>
</format>
<args>
<arg evaluator="xml" expression="get-property('first-json')"/>
<arg evaluator="xml" expression="$body"/>
</args>
</payloadFactory>
<property name="messageType" value="application/json" scope="axis2"/>
<send/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Note that i have retrieved your jsons from mocked services from mocky.io web site.
Thanks.

Extract all particular field from JSON in mule esb

I have this json payload, I would want to collect all externalListingId in one shot -
{
"listings": {
"numFound": 3,
"listing": [
{
"status": "INACTIVE",
"pricePerTicket": {
"amount": 100,
"currency": "USD",
},
"paymentType": "1",
"externalListingId": "12208278",
"city": "New York"
},
{ "status": "ACTIVE",
"pricePerTicket": {
"amount": 4444,
"currency": "USD"
},
"paymentType": "1",
"externalListingId": "CID1421798897102:151681733",
"city": "Seattle"
}
]
}
}
I am using MVEL expression -
<enricher target="#[flowVars['sData']]" source="#[(externalListingId in payload.listing)]" doc:name="Message Enricher">
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
</enricher>
But this is giving error !! - Message payload is of type: ReleasingInputStream.
Scenario - I would like to collect all externalListingId into flowVariable, convert to hashmap. I have another CSV file as input, would like to loop through that payload and check if this map contains the id!!
I am following this earlier post -
Extracting array from JSON in mule esb
You need to transform the message's streaming payload to an object with:
<json:json-to-object-transformer returnClass="java.lang.Object" />
before the enricher, and remove the one you have inside of it.
You also need to fix your MEL, as the listings property is missing in it:
source="#[(externalListingId in payload.listings.listing)]"
Source: http://www.mulesoft.org/documentation/display/current/Mule+Expression+Language+Tips#MuleExpressionLanguageTips-JSONProcessing
it worked with the same definition.
<flow name="test-mule-json-extractFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/json" doc:name="HTTP"/>
<enricher source="#[(externalListingId in payload.listings.listing)]" target="#[flowVars.ids]" doc:name="Message Enricher">
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
</enricher>
<logger message=":::::::::::::::#[flowVars.ids]" level="INFO" doc:name="Logger"/>
</flow>
Note: the json input you mentioned is not valid due to available of an extra comma.

How to extract all the JSON value in Mule ind insert to DB

I have a REST service in my Mule flow :-
<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 I have another flow which sends JSON request from a file to that service flow and consume it :-
<flow name="restFlow2" doc:name="restFlow2">
<file:inbound-endpoint path="E:\backup\test" responseTimeout="10000" doc:name="File" 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" doc:name="JSON to Object"/>
<http:outbound-endpoint exchange-pattern="request-response" contentType="application/json" method="GET" address="http://localhost:8082/getData/insert/?id=#[payload.insertDataRequest[0].id]&name=#[payload.insertDataRequest[0].name]&age=#[payload.insertDataRequest[0].age]&designation=#[payload.insertDataRequest[0].designation]" doc:name="HTTP"/>
</flow>
Now my JSON request is :-
{
"insertDataRequest": [
{
"id": "6",
"name": "ddddd",
"age": "55",
"designation": "WQQQQQ"
},
{
"id": "64",
"name": "mmmm",
"age": "545",
"designation": "TTTTTTTTTT"
}
]
}
Now, the issue is whenever I place the JSON request as a file ... only the first Data is inserted .. that is only
{
"id": "6",
"name": "ddddd",
"age": "55",
"designation": "WQQQQQ"
}
is getting inserted in DB ..
.... .... Now I want all the Data to be inserted in Database ... How can I achieve it ?? ..Do I need any for each to get all the Data ??... Please Help...
Use a for each block to iterate on the insertDataRequest entries:
<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>
Note that the fact you're performing insertions with GET instead of a POST is not respectful of the REST principles...