How to send array in url in mule esb? - mule

I need to send array in url. I have tried different ways like
http://localhost:8081/?RedundedItems[]=[00,11]
http://localhost:8081/?RedundedItems[]=00,11
http://localhost:8081/?RedundedItems=00&RedundedItems=11
http://localhost:8081/?RedundedItems[]=00&RedundedItems[]=11
Please assist me.

Sorry but I really dont think this is possible or even if by some miracle it is, I dont see it as practical...
One solution would be to send your data as normal and maybe process it into an array via datamapper?
Hope I have been of some help.
JB

The following works using your third option:
<flow name="request-testFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<set-payload value="#[message.inboundProperties.'http.query.params'.getAll('RedundedItems')]" doc:name="Set Payload"/>
<object-to-string-transformer doc:name="Object to String"/>
</flow>
So hitting http://localhost:8081/?RedundedItems=00&RedundedItems=11 the output is: [00, 11].
HTH.

The right way is http://localhost:8081/?RedundedItems=00,11 . You can't specify the parameter is an array.

Related

mule org.json.JSONObject returning property value as null though the json property does have value for it

I am using the below code to convert the input payload string to json in mule. The below code sometimes working and sometimes not. its not working on standalone and working on studio. Not able to nail down the exact cause for it. but based on the loggers that i see that the property value is coming null after the expression statement. i am suspecting this could be with the jar that's getting used here. i am still digging further on it.
<logger message="input: #[payload]" level="INFO" doc:name="Logger"/>
<set-payload value="#[payload.'data']" mimeType="application/json" doc:name="Set Payload" encoding="ISO-8859-2"/>
<logger message="createConnection: #[payload]" level="INFO" doc:name="Logger"/>
<expression-component doc:name="Expression"><![CDATA[String input = payload;
payload = new org.json.JSONObject(input);
]]></expression-component>
<logger message="before json to object: #[payload.con_id] #[payload.'con_id']" level="INFO" doc:name="Logger"/>
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
Input JSON:
data: {"name":"QA_tst2","description":"tst","con_id":10,"con_connection_id":null,
"verticalParam":[{"param_value":"abc","param_name":"Host"},{"param_value":"21","param_name":"Port"}],"CON_CATEGORY_NAME":"File"}
I don't think that notation will work for JSONObject, try using
payload.get('con_id')
as per the javadoc: https://stleary.github.io/JSON-java/org/json/JSONObject.html.
The reason this won't work with the notation you have tried, is that Mule supports that notation for Maps, and org.json.JSONObject does not implement java.util.Map. You could try using javax.json.JSONObject instead, which will support that notation.
I have figured out the current issue. if there is any logger added to fetch the properties from the payload right after the expression component then its screwing up further. if you just remove the logger that was added after the expression component then after json to object conversion, i am able to fetch the values. that solves the current issue. but i would like to understand the difference between fetching the properties #[payload.con_id] vs #[payload.'con_id']. i can start a separate conversation for the same.

How to convert org.glassfish.grizzly.utils.BufferInputStream to JSON in Mule?

On my first steps with Mule I'm writing a basic Http Proxy.
Currently I forward the request to the api server and what I'd like to do is reading the payload that I receive from it before responding to the client.
When I try to log it with #[payload] it prints
org.glassfish.grizzly.utils.BufferInputStream#2306df30
How can I print it properly in JSON format?
The full code:
<flow name="proxy">
<http:listener config-ref="http-lc-0.0.0.0-8081" path="![p['proxy.path']]" parseRequest="false"/>
<http:request config-ref="http-request-config" method="#[message.inboundProperties['http.method']]"
path="#[message.inboundProperties['http.request.path'].substring(message.inboundProperties['http.listener.path'].length()-2)]" parseResponse="false">
<http:request-builder>
<http:query-params expression="#[message.inboundProperties.'http.query.params']"/>
</http:request-builder>
<http:success-status-code-validator values="0..599" />
</http:request>
<logger doc:name="Logger" level="INFO" message="Payload #[payload]"/>
The payload after HTTP request is generally in stream format, ref:- https://docs.mulesoft.com/mule-user-guide/v/3.7/http-request-connector
There are two ways you can get the payload after http:request
1) <object-to-string-transformer doc:name="Object to String"/> after http:request
or
2) using a logger and use MEL expression <logger message="#[message.payloadAs(java.lang.String)]" level="INFO" doc:name="Logger"/>
Try #[message.payloadAs(java.lang.String)] which will log the expected output.
Hope this helps.
The http component will send as InputStream,So use byte array to string transformer after http component.If you just want to print you can use #[message.payloadAs(java.lang.String)] but you wanna do any operation just drag and drop a byte array to string transformer
Simplest way is to just use <object-to-string-transformer doc:name="Object to String"/> after http request component and then place a logger with #[payload].
One way to make sure that you get proper JSON response is to set payload as application/json mimetype.
<set-payload value="#[payload]" mimeType="application/json" doc:name="Set Payload"/>
Add this line after the HTTP Request. Just setting the payload value as #[payload] will convert it to json While converting it to string will just print it as string and not make it Json type.

Aggregate data from for-each loop

Scenario - Converting a csv file to json format, taking each json element and making a get request api call. I am doing this in a for-each loop sequence. I am getting a json response (extracting eventId and cost from each). Now I wish to club all these responses together under the main header listings and make a bigger json payload.
For example:
{
"listings": [
{
"eventId":"8993478",
"cost":34
},
{
"eventId":"xxxxxyyyy",
"cost":zz
},
]
}
How would I do this for all iteration entries. I can do it for a single entry(using groovy script).
You could define a variable before the for-each loop as an empty list with:
<set-variable variableName="listings" value="#[[]]" />
Then, on each iteration inside the for-each loop add an element to the previous variable with:
<expression-transformer expression="#[flowVars.listings.add(flowVars.iterationMap)]" />
In the previous code fragment I used the variable flowVars.iterationMap to denote the map generated on each iteration.
Finally, if needed, you can add a set-payload transformer after the for-each loop:
<set-payload value="#[flowVars.listings]" />
HTH, Marcos
You can use the Batch module but you would have to rewrite this logic a little bit different. For example, you will no longer be able to use an aggregation flowVar like Marcos suggested. Instead, you would need to use a fixed size batch:commit block (which would actually be better in many ways, for example you could start sending bulks to the remote API while still processing some of the other records in the background).
...I like Marco's answer and it worked perfectly for my use case.
Simply creating an array in a flow variable and using the add() method on the array in a ForEach scope did the trick.
The OP follow up question was a good one. It prompted me to do an alternate test using the approach suggested. See both of my flows here:
<flow name="sampleAggregatorFlow" doc:description="this is a simple demo that shows how to aggregate results into an accumulator array">
<http:listener config-ref="manage-s3-api-httpListenerConfig" path="/aggregate" allowedMethods="GET" doc:name="HTTP"/>
<set-payload value="#[['red','blue','gold']]" doc:name="Set Payload"/>
<set-variable variableName="accumulator" value="#[[]]" doc:name="accumulator"/>
<foreach doc:name="For Each">
<expression-transformer expression="#[flowVars.accumulator.add(payload)]" doc:name="addEm"/>
</foreach>
<set-payload value="#[flowVars.accumulator]" doc:name="Set Payload"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
<flow name="Copy_of_sampleAggregatorFlow" doc:description="this is a simple demo that shows how to aggregate results into an accumulator array">
<http:listener config-ref="manage-s3-api-httpListenerConfig" path="/aggregate2" allowedMethods="GET" doc:name="Copy_of_HTTP"/>
<set-payload value="#[['red','blue','gold']]" doc:name="Copy_of_Set Payload"/>
<set-variable variableName="accumulator" value="#[new java.util.ArrayList()]" doc:name="Copy_of_accumulator"/>
<foreach doc:name="Copy_of_For Each">
<expression-transformer expression="#[flowVars.accumulator.add(payload)]" doc:name="Copy_of_addEm"/>
</foreach>
<set-payload value="#[flowVars.accumulator]" doc:name="Copy_of_Set Payload"/>
<json:object-to-json-transformer doc:name="Copy_of_Object to JSON"/>
</flow>
Both flows produced the same outcome:
[
"red",
"blue",
"gold"
]
Tests conducted 12/26/2017 with Anypoint Studio 6.4.1 and wth Mule Runtime 3.9

How to Extract the Flow Name and MessageProcessor Name using MEL - MULE ESB

I'm not sure, how can we extract the flow-name and message-processor Name through MEL. For example I have multiple message processor. For logging, i need to extract the flow Name and Message-processor, so that I can find out transaction has crossed this particular flow and its message processor. Is there any simple way to find out. Please guide me. Please find the screenshot below. Here i need to Extract - set payload and its flowName (flow1)
Thanks in advance.
For mule 3.8+ version onwards #[flow.name] don't work.
Use #[mule:context.serviceName] expression in logger or component to extract the name of the flow
I know this post is old but I have been trying to find a way to do this in MEL for error handling emails.
For the flow name you can use #[exception.event.flowConstruct.name]
for the failing message processor you can use #[exception.failingMessageProcessor].
Both of these work in MEL without the need to use an flowVar.
Please note however, that the failing processor does not always come back with a value but comes back with null, I'm not sure why.
You can extract the flow-name with MEL : #[flow.name]
<flow name="name" doc:name="name">
<http:inbound-endpoint address="http://localhost:8090/resources" doc:name="HTTP" />
<logger message="name of flow: #[flow.name]" level="INFO" doc:name="Logger"/>
<set-payload value="name" doc:name="Set Payload"/>
</flow>
or
flowConstruct.getName() in a Message Processor
Two ways to acthive this (from current flow name)
First one is -
<logger message="Current flowName: #[flow.name]" level="INFO" doc:name="Logger"/>
and the second one is -
<logger message="Current flowName: #[context:serviceName]" level="INFO" doc:name="Logger"/>

To create multiple records in salesforce using mule salescloud connector

I am trying to upload many records to salesforce via mule using (create bulk) operation.
I created the flow as below
<flow name="bulk_salesFlow1" doc:name="bulk_salesFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP"/>
<sfdc:create-bulk config-ref="Salesforce12" type="BulkMule__c" doc:name="Salesforce">
<sfdc:objects>
<sfdc:object>
<sfdc:inner-object key="Component__c">Transformer</sfdc:inner-object>
<sfdc:inner-object key="Use__c">Transforms the payload</sfdc:inner-object>
</sfdc:object>
<sfdc:object>
<sfdc:inner-object key="Use__c">Iterator</sfdc:inner-object>
<sfdc:inner-object key="Component__c">ForEach</sfdc:inner-object>
</sfdc:object>
</sfdc:objects>
</sfdc:create-bulk>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
I am getting error "Element: Object is not allowed to be repeated". I would like to know if I'm trying in the right way, if so what is wrong in the above flow.
Thank you in advance
I think this is just a problem with Mule Studio, and you should be able to run your flow if you just ignore the warnings.
If the warnings bother you, you can always use <sfdc:objects ref="#[something]"/> with a list of maps with field names corresponding to your SF object.