Type mismatch for 'mapObject' operator in Mule 3.8.0 DataWeave that worked in 3.9.0 - mule

I built an API project that builds and sends a SOAP request to another service, based on parameters sent to the API. I inadvertently built the project in Mule 3.9.0 EE, when our production and dev Mule environments are 3.8.0 EE. The project works fine locally in 3.9.0, and it runs in 3.8.0 until it builds the request in Dataweave. It reports the following exception in 3.8.0:
Root Exception stack trace:
com.mulesoft.weave.engine.ast.dynamic.UnexpectedOperationTypesException: Type mismatch for 'mapObject' operator
found :array, :function
required :object, :function
I use two Dataweaves to build the request. The first builds the prompts used in the SOAP request from the parameters. The second builds the SOAP request and inserts the prompts.
The first Dataweave:
%dw 1.0
%output application/json
---
[flowVars.parameterMap mapObject (value, key)->{
PROMPT: {
PSQueryName: "",
UniquePromptName: key,
FieldValue: value
}
}]
The second Dataweave:
%dw 1.0
%output application/xml encoding="UTF-8"
%namespace SOAP-ENV http://schemas.xmlsoap.org/soap/envelope/
%namespace wsse http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
%namespace qas http://xmlns.oracle.com/Enterprise/Tools/schemas/QAS_EXEQRY_SYNC_REQ_MSG.VERSION_1
%namespace qas1 http://xmlns.oracle.com/Enterprise/Tools/schemas/QAS_EXEQRY_SYNC_REQ.VERSION_1
---
{
SOAP-ENV#Envelope: {
SOAP-ENV#Header: {
wsse#Security #(SOAP-ENV#mustUnderstand: "1"): {
wsse#UsernameToken: {
wsse#Username: "someUsername",
wsse#Password #(Type: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"): "somePassword"
}
}
},
SOAP-ENV#Body: {
qas#QAS_EXEQRY_SYNC_REQ_MSG: {
qas1#QAS_EXEQRY_SYNC_REQ: {
QueryName: flowVars.queryName,
isConnectedQuery: "N",
OwnerType: flowVars.queryType,
BlockSizeKB: 0,
MaxRow: 0,
OutResultType: "webrowset",
OutResultFormat: "nonfile",
PROMPTS: payload.*PROMPT mapObject {
PROMPT: {
PSQueryName: $.PSQueryName when $.PSQueryName != "" otherwise {},
UniquePromptName: $.UniquePromptName,
FieldValue: $.FieldValue
}
}
}
}
}
}
}
In 3.9.0, the Dataweave transformed the SOAP request perfectly. In 3.8.0, it has issue with the PROMPTS: payload.*PROMPT mapObject statement in the second DataWeave.
What changed in 3.9.0 that made this work properly?
What work around can I do to resolve this issue in 3.8.0?

I solved this on my own by combining the two Dataweaves, which separating the two proved to be unnecessary.
It does not answer what changes occurred in 3.9.0 that allowed it to work in the original project.
%dw 1.0
%output application/xml encoding="UTF-8"
%namespace SOAP-ENV http://schemas.xmlsoap.org/soap/envelope/
%namespace wsse http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
%namespace qas http://xmlns.oracle.com/Enterprise/Tools/schemas/QAS_EXEQRY_SYNC_REQ_MSG.VERSION_1
%namespace qas1 http://xmlns.oracle.com/Enterprise/Tools/schemas/QAS_EXEQRY_SYNC_REQ.VERSION_1
---
{
SOAP-ENV#Envelope: {
SOAP-ENV#Header: {
wsse#Security #(SOAP-ENV#mustUnderstand: "1"): {
wsse#UsernameToken: {
wsse#Username: "someUser",
wsse#Password #(Type: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"): "somePassword"
}
}
},
SOAP-ENV#Body: {
qas#QAS_EXEQRY_SYNC_REQ_MSG: {
qas1#QAS_EXEQRY_SYNC_REQ: {
QueryName: flowVars.queryName,
isConnectedQuery: "N",
OwnerType: flowVars.queryType,
BlockSizeKB: 0,
MaxRow: 0,
OutResultType: "webrowset",
OutResultFormat: "nonfile",
PROMPTS: flowVars.parameterMap mapObject (value, key)->{
PROMPT: {
PSQueryName: "",
UniquePromptName: key,
FieldValue: value
}
}
}
}
}
}
}

Related

how to remove the xmlns attribute that gets added after my transformation?

I'm facing an issue when I transform a json input to an xml output. After transformation i want to remove the xmlns namespace before closing tag. These Namespace (xmlns:ind="." and xmlns:att="d") need to be removed
sample input:
{
"order": "Electronic",
"productId": 6548790,
"status": "COMPLETED",
"recieved": "YES",
"orderId": "12453",
"desc": "NASQ123",
"details": [{
"attributes": [{
"linetype": "DFU"
}]
}]
}
I'm using this below dataweave script:
%dw 2.0
output application/xml writeDeclaration=false
ns soapenv http://schemas.xmlsoap.org/soap/envelope/
ns ind .
ns att d
---
{
soapenv#Envelope:{
soapenv#Header: {},
soapenv#Body: {
ind#updateorder: {
ind#orderId: payload.orderId,
ind#orderName: payload.order,
ind#quantity: "5",
ind#order: {
att#productId: payload.productId,
att#desc: payload.desc,
att#shipping: "MAIL",
att#status: payload.status,
att#type1: payload.order,
att#recieved: payload.recieved,
att#otherDetails: payload. *details map ()-> {
att#details1: $.attributeS.linetype,
},
}
}
}
}
}
Current Ouput:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ind:updateorder xmlns:ind=".">
<ind:orderId>12453</ind:orderId>
<ind:orderName>Electronic</ind:orderName>
<ind:quantity>5</ind:quantity>
<ind:order>
<att:productId xmlns:att="d">6548790</att:productId>
<att:desc xmlns:att="d">NASQ123</att:desc>
<att:shipping xmlns:att="d">MAIL</att:shipping>
<att:status xmlns:att="d">COMPLETED</att:status>
<att:type1 xmlns:att="d">Electronic</att:type1>
<att:recieved xmlns:att="d">YES</att:recieved>
<att:otherDetails xmlns:att="d">
<att:details1/>
</att:otherDetails>
</ind:order>
</ind:updateorder>
</soapenv:Body>
</soapenv:Envelope>
However, This is my expected Output After Transformation is done:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<typ:updateorder>
<ind:orderId>12453</typ:orderId>
<ind:orderName>Electronic</typ:orderName>
<ind:quantity>5</typ:quantity>
<ind:order>
<att:productId>6548790</pur:productId>
<att:desc>NASQ123</pur:desc>
<att:shipping>MAIL</pur:shipping>
<att:status>COMPLETED</pur:status>
<att:type1>NA</pur:type1>
<att:recieved>YES</pur:recieved>
<att:otherDetails>
<pur:details1/>
</pur:otherDetails>
</typ:order>
</typ:updateorder>
</soapenv:Body>
</soapenv:Envelope>
What you are trying to get is not a valid XML. Because all name spaces used in an XML needs to be declared within the XML. While writing dataweave, when you add an element like ind#updateorder what you mean is "Add an element with name updateorder from the namespace ind".
If you really want the output without namespace declaration. you can think of it as you need an element with name ind:updateorder and not updateorder from ind.
In other words, replace ind#updateorder with "ind:updateorder" and similarly at other places. something like this
%dw 2.0
ns soapenv http://schemas.xmlsoap.org/soap/envelope/
output application/xml writeDeclaration=false
---
{
soapenv#Envelope: {
soapenv#Header: {},
soapenv#Body: {
"ind:updateorder": {
"ind:orderId": payload.orderId,
"ind:orderName": payload.order,
"ind:quantity": "5",
"ind:order": {
"att:productId": payload.productId,
"att:desc": payload.desc,
"att:shipping": "MAIL",
"att:status": payload.status,
"att:type1": payload.order,
"att:recieved": payload.recieved,
"att:otherDetails": payload.*details map () -> {
"att:details1": $.attributeS.linetype
}
}
}
}
}
}
However, as I mentioned earlier, this is not a valid XML. You can try the w3school validator or any other online tool to validate to check.

Import xml namespace from custom Dataweave module

I'm trying to create a custom Dataweave module for centralizing my custom XML namespaces.
I followed the official document of Mulesoft:https://docs.mulesoft.com/mule-runtime/4.3/dataweave-create-module
it states that: "When you import a custom module into another DataWeave script, any functions, variables, types, and namespaces defined in the module become available for use in the DataWeave body".
So I was expecting that I could create a module (in modules folder) containing my namespaces like this: Namespaces.dwl
ns myNs1 http://namespaces/my1
ns myNs2 http://namespaces/my2
import that module in another Dataweave like this:
%dw 2.0
import * from modules::Namespaces
output application/java
---
{
body: {
myNs1#Response: {
outcome: 'ACCEPTED'
}
} write "application/xml"
}
But I got this error:
The prefix myNs1 has not been previously declared using ns
I'm running on Mule 4.3.0
As aled have pointed out, it might have been a bug or incorrect information in the docs. From what I can see, the namespaces are properly imported but it seems that prefixes are expected to be declared locally.
You can use below:
%dw 2.0
import * from modules::Namespaces
output application/java
var myNs1Local = myNs1 as Namespace
---
{
body: {
myNs1Local#Response: {
outcome: 'ACCEPTED'
}
} write "application/xml"
}
which will result to the expected output.
{
body: "<?xml version='1.0' encoding='UTF-8'?>\n<myNs1:Response xmlns:myNs1=\"http://namespaces/my1\">\n <outcome>ACCEPTED</outcome>\n</myNs1:Response>" as String {class: "java.lang.String"}
} as Object {encoding: "UTF-8", mediaType: "*/*", mimeType: "*/*", class: "java.util.LinkedHashMap"}
Notice here that what I used as the prefix is the declared variable (myNs1Local) but it still write the prefix as referenced in Namespace.dwl

Setting Http response data as a varible in Mule4

I am trying to set http response values in variable. Below is response from http request
{
"kind": "drive#file",
"id": "1MxumGPQD9dH161BQJCoJ_",
"name": "2020_August",
"mimeType": "application/vnd.google-apps.folder"
}
How can i set only the id field in a variable after getting above reponse.
Am trying this logic in trans form message
%dw 2.0
output application/json
---
{
"id":payload.id
}
But giving me error
The content that's returned from your HttpRequest call is binary.
Try this:
%dw 2.0
output application/json
---
id: read(payload, "application/json").'id'
which should return what you're looking for:
{
"id": "1MxumGPQD9dH161BQJCoJ_"
}
If you are capturing that into a local variable, define the same using a set-variable, like this:
<set-variable value="#[read(payload, "application/json").'id']" doc:name="id" variableName="id"/>

Mule Dataweave: How to dynamically map HTTP response(JSON) to XML output

I am building an application, where I have to hit a restful interface, and pass a specific section of the response to the UI.
The response model is quite huge with a lot of fields(String, array of objects, object,number datatypes), so using manual transformation is a big pain.
Is there a way to map the section of the response to a variable and directly send it to the UI.
I tried,
%dw 2.0
%output application/xml
%var UserAcct= payload.UserResponse.UserDetailsResp.UserAccounts
---
{
User: {
"UserAccount": {
Account: UserAcct
}
}
}
This doesn't work because, the payload has List, Array of Objects etc in the response and mapping to a variable throws an error. Is it possible to send the section payload.UserResponse.UserDetailsResp.UserAccounts directly in dataweave?? Please help.
It will be more helpful if you add Input payload, error and XML output.
Following is the code just by assuming your scenario. You can give this a try:
%dw 2.0
output application/xml
---
{
User: {
"UserAccount": {
(payload.UserResponse.UserDetailsResp.UserAccounts map {
Address:{
<XMLFieldName>: $.<respectiveJSONFieldToMap>
....
}
})
}
}
}

How to do mapping as arraylist of maps for below using dataweave mule

How to do mapping for below data.
ParameterMap{[card=[15242424211], phone=[54545454545]]}
This data is dynamic which is coming from http request as part queryparameters. I want to form query params in the form #[{'p1':'v1', 'p2':'v2'}] dynamically
for example into [{'card': '15242424211','phone':'54545454545'}]
i.e Array of maps(application/java) Using Dataweave in mule
can you please help on this
use following code
%dw 1.0
%output application/json
---
inboundProperties."http.query.params" mapObject {
($$) : $[0]
}
With this output will be {"card": "15242424211","phone":"54545454545"} you can wrap it under array if required by using
%dw 1.0
%output application/json
---
[inboundProperties."http.query.params" mapObject {
($$) : $[0]
}]
This will produce output as [{"card": "15242424211","phone":"54545454545"}]
Please refer org.mule.module.http.internal.ParameterMap for details of HTTP params.
Hope this help.
Update:-
Please use following for setting query parameters for HTTP outbound request.
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
inboundProperties."http.query.params" mapObject {
($$) : $[0]
}
]]></dw:set-payload>
</dw:transform-message>