How to process response in mule ESB - mule-studio

I am trying to write data weave to add the price in the response xml.
Request xml looks like
<?xml version="1.0" encoding="UTF-8"?>
<UniversityResponse xmlns="urn:abc:api:Components">
<Timestamp>2015-12-16T22:05:41.229Z</Timestamp>
<Dept>IT</Dept>
<Fees>
<Fee>
<Name>John</Name>
<Fee currencyID="USD">1.0</Fee>
</Fee>
<Fee>
<Name>Enrique</Name>
<Fee currencyID="USD">3.0</Fee>
</Fee>
<Fee>
<Name>Mary</Name>
<Fee currencyID="USD">2.0</Fee>
</Fee>
<Fee>
<Name>Meena</Name>
<Fee currencyID="USD">0.5</Fee>
</Fee>
</Fees>
</UniversityResponse>
As of now i wrote like
%dw 1.0
%namespace ns0 urn:abc:api:Components
%output application/xml
---
TotalFees:{
plus : payload.ns0#UniversityResponse.ns0#Fees.*ns0#Fee[0].ns0#Fee +
payload.ns0#UniversityResponse.ns0#Fees.*ns0#Fee[0].ns0#Fee +
payload.ns0#UniversityResponse.ns0#Fees.*ns0#Fee[1].ns0#Fee +
payload.ns0#UniversityResponse.ns0#Fees.*ns0#Fee[2].ns0#Fee +
payload.ns0#UniversityResponse.ns0#Fees.*ns0#Fee[3].ns0#Fee
}
Output :
<TotalFees>
<plus>6.5</plus>
</TotalFees>
How Can i loop the complex tag in the response xml ?
Basically i want to create one loop for UniversityResponse/Fees. Inside the loop i want to write something like Plus = Plus + "UniversityResponse/Fees/Fee[counter].Fee"

That was kind of a headbreaker because i was looking for a SUM function in the docs, not in the docs but it is in the language :)
--
%dw 1.0
%output application/xml
%namespace ns0 urn:abc:api:Components
---
TotalFees: plus: sum payload.ns0#UniversityResponse.ns0#Fees.*ns0#Fee.ns0#Fee
<?xml version='1.0' encoding='UTF-8'?>
<TotalFees>
<plus>6.5</plus>
</TotalFees>

Related

Karate: Replace text at Envelope level [duplicate]

I need to parse and print ns4:feature part. Karate prints it in json format. I tried referring to this answer. But, i get 'ERROR: 'Namespace for prefix 'xsi' has not been declared.' error, if used suggested xPath. i.e.,
* def list = $Test1/Envelope/Body/getPlan/planSummary/feature[1]
This is my XML: It contains lot many parts with different 'ns' values, but i have given here an extraxt.
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header/>
<S:Body>
<ns9:getPlan xmlns:ns10="http://xmlschema.test.com/xsd_v8" xmlns:ns9="http://xmlschema.test.com/srv/SMO_v4" xmlns:ns8="http://xmlschema.test.com/xsd/Customer_v2" xmlns:ns7="http://xmlschema.test.com/xsd/Customer/Customer_v4" xmlns:ns6="http://schemas.test.com/eca/common_types_2_1" xmlns:ns5="http://xmlschema.test.com/xsd/Customer/BaseTypes_1_0" xmlns:ns4="http://xmlschema.test.com/xsd_v4" xmlns:ns3="http://xmlschema.test.com/xsd/Enterprise/BaseTypes/types/ping_v1" xmlns:ns2="http://xmlschema.test.com/xsd/common/exceptions/Exceptions_v1_0">
<ns9:planSummary xsi:type="ns4:Plan" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns5:code>XPBSMWAT</ns5:code>
<ns5:description>Test Plan</ns5:description>
<ns4:category xsi:nil="true"/>
<ns4:effectiveDate>2009-11-05</ns4:effectiveDate>
<ns4:sharingGroupList>
<ns4:sharingCode>CAD_DATA</ns4:sharingCode>
<ns4:contributingInd>true</ns4:contributingInd>
</ns4:sharingGroupList>
<ns4:feature>
<ns5:code>ABC</ns5:code>
<ns5:description>Service</ns5:description>
<ns5:descriptionFrench>Service</ns5:descriptionFrench>
<ns4:poolGroupId xsi:nil="true"/>
<ns4:switchCode/>
<ns4:type/>
<ns4:dtInd>false</ns4:dtInd>
<ns4:usageCharge>0.0</ns4:usageCharge>
<ns4:connectInd>false</ns4:connectInd>
</ns4:feature>
</ns9:planSummary>
</ns9:getPlan>
</S:Body>
</S:Envelope>
This is the xPath i used;
Note: I saved above xml in a separate file test1.xml. I am just reading it and parsing the value.
* def Test1 = read('classpath:PP1/data/test1.xml')
* def list = $Test1/Envelope/Body/*[local-name()='getPlan']/*[local-name()='planSummary']/*[local-name()='feature']/*
* print list
This is the response i am getting;
16:20:10.729 [ForkJoinPool-1-worker-1] INFO com.intuit.karate - [print] [
"ABC",
"Service",
"Service",
"",
"",
"",
"false",
"0.0",
"false"
]
How can i get the same in XML?
This is interesting, I haven't seen this before. The problem was you have an attribute with a namespace xsi:nil="true" which is causing problems when you take a sub-set of the XML but the namespace is not defined anymore. If you remove it first, things will work.
Try this:
* remove Test1 //poolGroupId/#nil
* def temp = $Test1/Envelope/Body/getPlan/planSummary/feature
Another approach you could have tried is to do a string replace to remove troublesome stuff in the XML before doing XPath.
EDIT: added info on how to do a string replace using Java. The below will strip out the entire xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns4:Plan" part.
* string temp = Test1
* string temp = temp.replaceAll("xmlns:xsi[^>]*", "")
* print temp
So you get the idea. Just use regex.
Also see: https://stackoverflow.com/a/50372295/143475

How To Preserve SOAP Headers to use with Mule 4 Web Service Consumer?

I have used an Existing WSDL to create an Experience API where I am performing several steps before either:
Passing the SOAP Request Message as-is to the Original Backend System using Mule4 Web Service Consumer or
Calling another Backend System (RESTful API) and transforming the Response to match the Expected SOAP Response Message
Sample Message
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="urn:Acme/PublicService/V1" xmlns:ns0="urn:/Acme/BasicDataPublicService/V1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header>
<a:Action s:mustUnderstand="1" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">urn:Acme/PublicService/V1/PublicService/SetCustomer</a:Action>
<a:MessageID xmlns:a="http://www.w3.org/2005/08/addressing">urn:uuid:4afe0693-adea-4ede-bec9-10b694708d85</a:MessageID>
<a:ReplyTo xmlns:a="http://www.w3.org/2005/08/addressing">
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo8KxyyGpakdIj8o84JOeAMsAAAAAQBkt3vfAK0C4dDgn3rAKx/iXgqYosnhKv/OHgph9cXoACQAA</VsDebuggerCausalityData>
<a:To s:mustUnderstand="1" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">http://316.820.517.311:36990/PublicInterface/Service</a:To>
<AuthorizationToken xmlns="urn:Acme/Authorization/V1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CultureName>uk-UK</CultureName>
<OnBehalfOf i:nil="true"></OnBehalfOf>
<Password>****</Password>
<UserName>sa-ACME</UserName>
</AuthorizationToken>
</env:Header>
<env:Body>
<ns:SetCustomer>Muli-Tier Message</ns:SetCustomer>
</env:Body>
</env:Envelope>
According to Mulesoft KB; this requires additional Transformation steps in the beginning of the flow. Passing the SOAP Body is not an issue; the SOAP Header is a pickle, however. Especially since the KB document is hard-coding the values; while in my case these need to be dynamic (i.e. coming from the Original SOAP Request message).
I tried mapping the Header Parameters to a Variable as described but I cannot seem to get to it.
Option 1 Mapping the Header Elements to Children Attributes of a Variable, results in the Variable Storing Null
%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
ns ns0 http://www.w3.org/2005/08/addressing
ns s http://www.w3.org/2003/05/soap-envelope
---
headers: {
ns0#Action #(s#mustUnderstands: payload.headers.Action.#mustUnderstands): payload.headers.Action as String default null,
ns0#MessageID: payload.headers.MessageID as String default null,
ns0#ReplyTo: {
ns0#Address: payload.headers.ReplyTo.Address as String default null
},
VsDebuggerCausalityData: payload.headers.VsDebuggerCausalityData as String default null,
ns0#To #(s#mustUnderstands: payload.headers.To.#mustUnderstands): payload.headers.To as String default null,
AuthorizationToken: {
CultureName: payload.headers.AuthorizationToken.CultureName as String default null,
OnBehalfOf: payload.headers.AuthorizationToken.OnBehalfOf as String default null,
Password: payload.headers.AuthorizationToken.Password as String default null,
UserName: payload.headers.AuthorizationToken.UserName as String default null
}
}
Option 2 Mapping payload.headers to a Variable, results in extra tags; and losing the XML Tag attributes
%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
ns ns0 http://www.w3.org/2005/08/addressing
ns s http://www.w3.org/2003/05/soap-envelope
---
headers: payload.headers
It seems there is an issue with the WebService Consumer connector when generating the SOAP Envelope Header.
Instead of using the WebService Consumer Connector, try using an HTTP Request Connector passing the payload as-is.
I will come back and add more details on the answer, but here is how to solve that issue:
%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
---
headers: (payload.headers.headers mapObject (value, key) -> {
(value)
})

Attachment missing in MTOM response from Citrus SOAP server simulation

I have built a sample Citrus testcase to simulate a SOAP server that responds with an MTOM attachment.
runner.soap(action -> action.server("simulationServer")
.receive()
...[validation etc]
);
runner.soap(action -> action.server("simulationServer")
.send()
.name("get-response")
.mtomEnabled(Boolean.TRUE)
.attachment("myAttachment", "application/octet-stream", new ClassPathResource("testfiles/myAttachment.pdf"))
.payload("<getResponse xmlns:xmime=\"http://www.w3.org/2005/05/xmlmime\">\n" +
" <document>\n" +
" <contentElements>\n" +
" <contentElement xmime:contentType=\"application/pdf\">cid:myAttachment</contentElement>\n" +
" </contentElements>\n" +
" <id>Test</id>\n" +
" </document>\n" +
"</getResponse>\n")
);
When I run this test and call the Citrus simulation with SoapUI, I see the contents of myAttachment.pdf in the debug logs. So at least it looks like Citrus tries to send the attachment.
However, in SoapUI I do not get an attachment. There is a XOP element in the SOAP response, but no attachment. The RAW view of SoapUI of the Citrus response looks like this.
HTTP/1.1 200 OK
Date: Tue, 16 Jan 2018 15:30:36 GMT
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: Multipart/Related; boundary="----=_Part_0_382348859.1516116636524"; type="application/xop+xml"; start-info="text/xml"
Transfer-Encoding: chunked
Server: Jetty(9.4.6.v20170531)
------=_Part_0_382348859.1516116636524
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><getResponse xmlns:xmime="http://www.w3.org/2005/05/xmlmime">
<document>
<contentElements>
<contentElement xmime:contentType="application/pdf"><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:myAttachment"/></contentElement>
</contentElements>
<id>Test</id>
</document>
</getResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
------=_Part_0_382348859.1516116636524--
In an MTOM response with attachment the attachment starts where this RAW view ends. It should continue like this
------=_Part_0_382348859.1516116636524-- [last line from above]
Content-Type: application/pdf
Content-Transfer-Encoding: binary
Content-ID: <myAttachment>
%PDF-1.4... [PDF content]
I am using Citrus 2.7.2 release.
Update
Still no success on this. Wireshark shows the same picture as SoapUI: the attachment is missing in the response.
However, when I debug into the code on the server (Citrus) side, I see the attachment in the response message until I get lost somewhere in a MessageSendingTemplate. Same on the console log. The message has the attachment.
There is an inline MTOM variant in the Citrus documentation, but I can't find a way to set this mtom-inline on the attachment in Java config.
Any hints, where to set a breakpoint to find where the attachment get lost? Or any other suggestions/examples on the Citrus side?
The setMtomInline field sits on the SoapAttachment interface. I am not sure if I got the setup right - but seems to work for inlined attachements - fails for soap attachements / multipart. The SoapUI Mock does not show any attachements when receiving requests from following testcase.
SoapAttachment soapAttachment = new SoapAttachment();
soapAttachment.setMtomInline(false);
soapAttachment.setContentResourcePath("log4j.xml");
soapAttachment.setContentType("application/octet-stream");
soapAttachment.setContentId("FILE");
SoapMessage soapMessage = new SoapMessage();
soapMessage.mtomEnabled(true);
soapMessage.soapAction("/HelloService/sayHello");
soapMessage.setPayload(
"<ht:HelloRequest " +
"xmlns:ht=\"http://citrusframework.org/schemas/samples/HelloMtomService\" " +
"xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" >\n" +
" <ht:Message>Hei .. citrus does stream mtom</ht:Message>\n" +
" <ht:Data><xop:Include href=\"cid:FILE\"/></ht:Data>\n" +
"</ht:HelloRequest>");
soapMessage.addAttachment(soapAttachment);
runner.soap(action -> {
action.client("helloMtomSoapuiClient")
.send()
.soapAction("/HelloService/sayHello")
.message(soapMessage);
});
If I do the same for MtomInline set to true, I see the attachement as base64 encoded content text in the ht:Data node.
SoapAttachment soapAttachment = new SoapAttachment();
soapAttachment.setContentResourcePath("log4j.xml");
soapAttachment.setMtomInline(true);
soapAttachment.setContentType("application/xml");
soapAttachment.setContentId("MyAttachement");
soapAttachment.setEncodingType("base64Binary");
runner.soap(action -> {
action.client("helloMtomSoapuiClient")
.send()
.soapAction("/HelloService/sayHello")
.mtomEnabled(true)
.payload("<ht:HelloRequest xmlns:ht=\"http://citrusframework.org/schemas/samples/HelloMtomService\">\n" +
" <ht:Message>Hei .. citrus does mtom</ht:Message>\n" +
" <ht:Data>cid:MyAttachement</ht:Data>\n" +
"</ht:HelloRequest>")
.attachment(soapAttachment);
});
Either soapUI or citrus swallows the attachement. Some help or working JavaDSL sample would be nice.
It was actually a bug that will be fixed in Citrus 2.7.4 release. See https://github.com/christophd/citrus/issues/328
The inline MTOM variant with XML config works for me in the current release.
<ws:send endpoint="simulationServer" mtom-enabled="true">
<message>
<resource file="testfiles/simulation/get-response.xml" />
</message>
<ws:attachment content-id="myAttachment" content-type="application/octet-stream" mtom-inline="true" encoding-type="base64Binary">
<ws:resource file="classpath:testfiles/myAttachment.pdf"/>
</ws:attachment>
</ws:send>

Azure Table Service REST API: JSON format is not supported

I'm trying to request a line from Azure Table Storage using the REST API and C++, but always got the following error:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<cod_e>JsonFormatNotSupported</cod_e>
<message xml:lang="en-US">JSON format is not supported.
RequestId:0ccb3b9b-0002-0029-3389-0d2fa1000000
Time:2016-09-13T06:39:13.3155742Z</message>
</error>
Here is my request:
GET https://<myaccount>.table.core.windows.net/<mytable>(PartitionKey='<mypartition>',RowKey='<myrow>')?<sharedsignature>
Here how I fill request headers, as from https://msdn.microsoft.com/en-us/library/dd179428.aspx:
std::string sharedAccessSignature("<sharedsignature>");
std::string dateTime(GetDateTime());
std::string stringToSign(dateTime + "\n/" + account + "/" + "<mytable>");
std::string request("(PartitionKey='<mypartition>',RowKey='<myrow>')");
stringToSign += request;
std::string signatureString(HMACSHA256(stringToSign, sharedAccessSignature));
headers["Authorization"] = "SharedKeyLite " + account + ":" + signatureString;
headers["DataServiceVersion"] = "3.0;NetFx";
headers["MaxDataServiceVersion"] = "3.0;NetFx";
headers["x-ms-version"] = "2015-12-11";
headers["x-ms-date"] = dateTime;
headers["Accept"] = "application/json;odata=verbose";
headers["Accept-Charset"] = "UTF-8";
The table exists and is not empty.
Please advise what's wrong?
Update 1
Removing sharedsignature from request, i.e. GET https://<myaccount>.table.core.windows.net/<mytable>(PartitionKey='<mypartition>',RowKey='<myrow>') leads to the same result.
Removing Authorization header from the request leads to the same result too.
Update 2
Putting https://<myaccount>.table.core.windows.net/<mytable>(PartitionKey='<mypartition>',RowKey='<myrow>')?<sharedsignature> in a browser produces a valid response, but in Atom format.
<?xml version="1.0" encoding="utf-8"?>
<entry
xml:base="https://<myaccount>.table.core.windows.net/"
xmlns="http://www.w3.org/2005/Atom"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
m:etag="W/"datetime'2016-09-13T05%3A29%3A51.211538Z'"">
<id>https://<myaccount>.table.core.windows.net/<mytable> (PartitionKey='<mypartition>',RowKey='<myrow>')</id>
<category term="<myaccount>.<mytable>" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="<mytable>" href="<mytable> (PartitionKey='<mypartition>',RowKey='<myrow>')" />
<title />
<updated>2016-09-13T11:25:19Z</updated>
<author><name /></author>
<content type="application/xml">
<m:properties>
<d:PartitionKey><mypartition></d:PartitionKey>
<d:RowKey><myrow></d:RowKey>
<d:Timestamp m:type="Edm.DateTime">2016-09-13T05:29:51.211538Z</d:Timestamp>
<d:Score m:type="Edm.Int32">1050</d:Score>
</m:properties>
</content>
</entry>
Update 3
Investigation situation using curl I found that adding Accept: application/json;odata=fullmetadata to the request headers leads to the error above. Default Accept */* in headers produces valid Atom response.
Finally, got it!
The issue was in my shared signature.
While looking at it I found sv=2012-02-12 part, and assumed, that it means API version. The version, before JSON support was introduced! I created a new shared signature and finally got JSON with the following curl command.
curl -v -H "Accept: application/json;odata=nometadata" -H "x-ms-version: 2015-12-11" "https://<myaccount>.table.core.windows.net/<mytable>(PartitionKey='<mypartition>',RowKey='<myrow>')?<mysharedsignature>"
So, for everyone, who face the same issue in the future: please check your signature first!

Http client POST request xml+soap

I want to make a post request in Scala to this API http://api.atinternet-solutions.com/toolbox/reporting.asmx
I first did it with a curl like this :
curl -X POST -T post.txt -H "Content-Type: application/soap+xml; charset=utf-8" http://api.atinternet-solutions.com/toolbox/reporting.asmx -v
and I got what I expected.
Now I want to call the API programatically with a simple HttpClient
val httpClient = new DefaultHttpClient()
def postRequest=new HttpPost("https://api.atinternet-solutions.com/toolbox/reporting.asmx")
postRequest.addHeader("Content-Type","application/soap+xml ; charset=utf-8")
postRequest.addHeader("SOAPAction","\"http://www.xiti.com/queryReport\"")
val file=new File("post.txt")
val fe=new FileEntity(file,"application/soap+xml;charset=utf-8")
postRequest.setEntity(fe)
val httpResponse=httpClient.execute(postRequest)
println(httpResponse.getStatusLine.toString)
val rspStr=Source.createBufferedSource(httpResponse.getEntity.getContent).mkString
println(rspStr)
but I get an HTTP/1.1 500 Internal Server Error
and printing the rspStr yields
"?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:Receiver</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">Server was unable to process request. ---> Root element is missing.</soap:Text></soap:Reason><soap:Detail /></soap:Fault></soap:Body></soap:Envelope"
The post.txt looks like below, except I set the good information instead.
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<NXHeader xmlns="http://www.xiti.com/">
<GUID>string</GUID>
<SecurityKey>string</SecurityKey>
<Site>int</Site>
</NXHeader>
</soap12:Header>
<soap12:Body>
<queryReport xmlns="http://www.xiti.com/">
<startDate>int</startDate>
<endDate>int</endDate>
<query>string</query>
<param>string</param>
<typereport>XML or CSV</typereport>
</queryReport>
</soap12:Body>
</soap12:Envelope>
The curl action which is working is done from my scala project directory. I printed post.txt in scala and got the good content.
I cannot figure out what is going wrong. Thank you for your help
I tried your call with the dispatch library.
This is my code
import dispatch._
import java.io.File
object ToolBox {
val endpoint = url("https://api.atinternet-solutions.com/toolbox/reporting.asmx").POST
.addHeader("Content-Type","application/soap+xml ; charset=utf-8")
.addHeader("SOAPAction",""" "http://www.xiti.com/queryReport" """)
def report = Http( endpoint <<< new File("post.txt") > as.xml.Elem)
def tryReport = {
val res = report.either
for {
ex <- res.left
} yield "Something got wrong " + ex.getMessage
}
}
The service replies with a status 500 like you, but the faultString in the response xml is: A parameter is missing in your NXHeader or you have a namespace issue.
Is it what you would expect, since the post.txt body contains only the placeholders from the query report example, instead of real parameters?
I found what was going wrong.
Replace
def postRequest
by
val postRequest.
Tks again