Axis2 generated client convert <!CDATA to <![CDATA[ - soap

I generated an Axis2 client from a wsdl.
In the body of my request I need to send a value that should look like this:
String bodyRequest = "<inputXml>
<![CDATA[{
"pricing": {
"item": "AZ0225220",
"price": "2000",
}
}]]>
</inputXml>"
my snippet code:
PricingServiceStub serviceStub = new PricingServiceStub();
RunDocument runDocument = RunDocument.Factory.newInstance();
Run runRequestContent = Run.Factory.newInstance(options);
runRequestContent.setInputXml(bodyRequest);
runDocument.setRun(runRequestContent);
serviceStub.run(runDocument);
and when sending the request the <![CDATA[ tag is converted to <![CDATA[
Do you have any idea how to make sure that < is not converted to < when working with axis2?
Thank you in advance

Related

Clickatell One API Customer Call Back not returning anything

I have developed a call back REST service using the following link as reference https://docs.clickatell.com/channels/one-api/one-api-reference/#tag/One-API-Client-Callbacks/operation/sendPostOmniReplyCallback. I am using the sample payload as supplied by the Clickatell example using Postman and I can process and post the payload without problems. It also works when I deploy this as a public URL on the web. However, when pasting my URL in the Clickatell Customer Call Back I do not receive any call backs. I am obviously missing something or misinterpreting the sample code provided by Clickatell. Please note that for testing purposes I write the full payload to MySQL - works when using Postman, but not from Clickatell Call Back URL.
enter code here
{
[Route("client-callback/one-api-reply")]
[ApiController]
public class MessageController : ControllerBase
{
[HttpPost]
public async Task<dynamic> StartProcessiongAsync([FromBody] dynamic obj)
{
string myObj = JsonConvert.SerializeObject(obj);
var data = JsonConvert.DeserializeObject<Rootobject>(myObj);
var context = new DataContext();
var command = context.Database.GetDbConnection().CreateCommand();
context.Database.OpenConnection();
command = context.Database.GetDbConnection().CreateCommand();
{
command.CommandText =
"INSERT INTO testcallback(message) VALUES ('" + myObj + "');";
command.ExecuteNonQuery();
}
return Ok(obj);
}
}
}
Postman Payload Sample
{
"integrationId": "fa8090815f05d5ed015f0b5b56080cd2",
"integrationName": "My integration",
"event": {
"moText": [
{
"channel": "sms",
"messageId": "3a89680503414383af44dcd0e4e5f184",
"relatedMessageId": "d33eef0838a121f71069a4cc8d55c19e",
"relatedClientMessageId": "d33eef0838a121f71069a4cc8d55c19e",
"from": "2799900001",
"to": "2799900001",
"timestamp": 1506607698000,
"content": "Text Content of the reply message",
"charset": "UTF-8",
"sms": {
"network": "Network ID"
},

node-soap adding namespace to envelope

I am trying to consume this soap service: http://testws.truckstop.com:8080/v13/Posting/LoadPosting.svc?singleWsdl with node-soap, but the client is mangling the namespaces and I have been unable to find a working solution.
I believe the answer is to either add a namespace to the soap envelope, or overwrite the soap envelope.
Using Soap UI, the request should look like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v11="http://webservices.truckstop.com/v11"
xmlns:web="http://schemas.datacontract.org/2004/07/WebServices">
<soapenv:Header/>
<soapenv:Body>
<v11:GetLoads>
<v11:listRequest>
<web:IntegrationId>integrationId</web:IntegrationId>
<web:Password>password</web:Password>
<web:UserName>username</web:UserName>
</v11:listRequest>
</v11:GetLoads>
</soapenv:Body>
</soapenv:Envelope>
However, when I do:
client = soap.createClient(url);
let query = {
listRequest: {
Password: password,
UserName: username,
IntegrationId: integrationId
}
};
let results = client.GetLoads(query);
The client generates this xml:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:tns="http://webservices.truckstop.com/v11"
xmlns:q1="http://schemas.datacontract.org/2004/07/WebServices.Posting"
xmlns:q2="http://schemas.datacontract.org/2004/07/WebServices.Objects"
xmlns:q3="http://schemas.datacontract.org/2004/07/WebServices.Posting"
xmlns:q4="http://schemas.datacontract.org/2004/07/WebServices.Objects"
xmlns:q5="http://schemas.datacontract.org/2004/07/WebServices.Posting"
xmlns:q6="http://schemas.datacontract.org/2004/07/WebServices.Objects"
xmlns:q7="http://schemas.datacontract.org/2004/07/WebServices.Posting"
xmlns:q8="http://schemas.datacontract.org/2004/07/WebServices.Objects"
xmlns:q9="http://schemas.datacontract.org/2004/07/WebServices.Posting"
xmlns:q10="http://schemas.datacontract.org/2004/07/WebServices.Objects"
xmlns:q11="http://schemas.datacontract.org/2004/07/WebServices.Posting"
xmlns:q12="http://schemas.datacontract.org/2004/07/WebServices.Objects">
<soap:Body>
<GetLoads xmlns="http://webservices.truckstop.com/v11">
<listRequest>
<ns1:IntegrationId>integrationId</ns1:IntegrationId>
<ns1:Password>password</ns1:Password>
<ns1:UserName>usernam</ns1:UserName>
</listRequest>
</GetLoads>
</soap:Body>
</soap:Envelope>
This fails because IntegrationId, Password and UserName need http://schemas.datacontract.org/2004/07/WebServices, but the namespace isn't referenced in the envelope.
I've tried updating the client to add the namespace as suggested here:
client.wsdl.definitions.xmlns.ns1 = "http://schemas.datacontract.org/2004/07/WebServices";
client.wsdl.xmlnInEnvelope = client.wsdl._xmlnsMap();
I can see the namespace in client.wsdl.xmlnInEnvelope, but it doesn't seem to change the actual generated xml.
Is there another step required to refresh the client to use the updated envelope?
I also tried overriding the root element as shown here:
var wsdlOptions = {
//namespaceArrayElements: "xmlns:ns1=http://schemas.datacontract.org/2004/07/WebServices"
"overrideRootElement": {
"namespace": "xmlns:tns",
"xmlnsAttributes": [{
"name": "xmlns:tns",
"value": "http://webservices.truckstop.com/v11"
}, {
"name": "xmlns:ns1",
"value": "http://schemas.datacontract.org/2004/07/WebServices"
}]
}
};
this.loadPostClient = soap.createClient(this.tsConfig.loadPostUrl, wsdlOptions);
This changes the root body element:
<soap:Body>
<xmlns:tns:GetLoads
xmlns:tns="http://webservices.truckstop.com/v11"
xmlns:ns1="http://schemas.datacontract.org/2004/07/WebServices">
<listRequest>
<ns1:IntegrationId>integrationId</ns1:IntegrationId>
<ns1:Password>password</ns1:Password>
<ns1:UserName>username</ns1:UserName>
</listRequest>
</xmlns:tns:GetLoads>
</soap:Body>
But the remote server doesn't understand.
Thank you for reading!
This answer was correct all along
It wasn't working for me due to autocomplete and similar fields
client.wsdl.xmlnInEnvelope = client.wsdl._xmlnsMap();
Should have been:
client.wsdl.xmlnsInEnvelope = client.wsdl._xmlnsMap();
I left out an s and was setting xmlnInEnvelope instead of xmlnsInEvelope
It's been a few years, but I ran into a similar need of adding custom attributes to the soap envelope and wanted to give an alternative.
As of this writing, that _xmlnsMap() is a private method on the WSDL class so you can use it at your own risk. I always take private methods as subject to change from the developer without any notice to the library consumers so I wanted to find another way and turns out its possible.
TL;DR - Create your own WSDL class instance and pass it to your own Client class instance.
Use the open_wsdl method to bring in your WSDL
Use the callback to build your own custom attributes in a concatenated string.
Assign the attributes to the public xmlnsInEnvelope property.
return the updated WSDL instance (I used a promise).
const fetchWSDL = new Promise<WSDL>((resolve, reject) => {
// method that returns a WSDL instance from a url/file path
open_wsdl(this.wsdl, (err: any, wsdl?: WSDL) => {
// Build custom attributes
if (wsdl && wsdl.definitions.xmlns) {
const xmlns: { [key: string]: string } = {
[your namespaces]: 'values',
};
// turn your custom attributes map into a single concatenated string
let str = '';
for (const alias in xmlns) {
const ns = xmlns[alias];
str += ' xmlns:' + alias + '="' + ns + '"';
}
// Leverage public attribute on WSDL instance to apply our custom attributes
wsdl.xmlnsInEnvelope = str;
resolve(wsdl);
}
reject(err);
});
});
Use the updated WSDL instance to create your own client.
NOTE: the createClient method is just a convenience wrapper for creating a WSDL instance and returning a new Client instance.
const ModifiedWSDL = await fetchWSDL;
// Create client with our modified WSDL instance
this.client = new Client(ModifiedWSDL)
// adjust your Client instance as needed
A bit more code that the OP, but hopefully more in line with node-soap types and safer to use if you plan to upgrade.

WireMock - invalid content-length after modify body by ResponseTransformer

I'm trying to modify response with wiremock in record mode.
I'm extending ResponseTransformer and replace an absolute url reference.
Wiremock returns modified response but doesn't update Content-Length header so chrome thinks there is few more bytes to download.
When i try add Content-Length header by :
...
Response.Builder.like(response).headers(updateContentLength(response.getHeaders(), modifiedBody.length()));
...
private HttpHeaders updateContentLength(HttpHeaders headers, int bodyLength) {
HttpHeaders newHttpHeaders = HttpHeaders.noHeaders();
for (HttpHeader header : headers.all()) {
if(header.key().equalsIgnoreCase("Content-Length"))
{
newHttpHeaders.plus(new HttpHeader(header.key(), bodyLength +""));
}
else
{
newHttpHeaders.plus(header);
}
}
return newHttpHeaders;
}
Some headers like Set-Cookie disappears
and "Transfer-Encoding: chunked" is added extra.
using:
wiremock-standalone-2.14.0.jar
1) The bug is reporoted here github.com/tomakehurst/wiremock/issues/907
2) My workaround is to not change actual content length by adding white characters in a place where a client ignores them e.g.
<script src="https://example123456.com/aaa"></script>
replace by:
<script src= "https://example.com/aaa"></script>

How to PUT XmlSlurper back to REST with HttpBuilder

I'm trying to make GET and then PUT call on XML REST web service.
I do it this way:
#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7')
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
import groovy.xml.XmlUtil
def url = "http://localhost:81"
def pathPrefix = "/api/v1"
def http = new HTTPBuilder(url)
def profile = http.request(GET, XML) { req ->
uri.path = "$pathPrefix/profiles/55"
response.success = {resp, xml ->
xml
}
}
println XmlUtil.serialize(profile) // this is fine!
Now i'm going to change and save
profile.name = "New Name"
// this is not fine (i have 400 Bad Request)
// because it sends body not in XML
def savedProfile = http.request(PUT, XML) { req ->
uri.path = "$pathPrefix/profiles/55"
body = profile
response.success = {resp, xml ->
xml
}
}
println XmlUtil.serialize(savedProfile)
When i make PUT request HTTPBuilder do not send XML. It sends string, made of profile.toString().
It it not what i'm expecting.
How to send XmlSlurper object (that i obtained earlier) in PUT request?
Thank you.
I think i found the solution.
When i define body configuration value, i have to write
body = {
mkp.yield profile
}

How do I extract the ACK from a webservice response in Mirth?

I have a destination which sends an HL7 v2 message to a WCF webservice. I've managed to get the message correctly to the webservice (after fixing various encoding problems) and I can confirm that the message is reaching the WCF endpoint correctly. However, after much hunting around in the forums and documentation, I am unable to correctly parse the ACK we receive back to indicate when an error has occurred.
The response coming back from the webservice looks like:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header/>
<s:Body>
<ProcessMessageResponse xmlns="http://www.bluewire-technologies.com/webservices">
<ProcessMessageResult>
MSH|^~\&|Epro|RGR|||||ACK||D||||||GBR|ASCII|
MSA|AE||Empty message|
ERR|^^^100|
</ProcessMessageResult>
</ProcessMessageResponse>
</s:Body>
</s:Envelope>
The response contains an ACK in the ProcessMessageResult element. How to I extract this ACK from the response and pass it as the output of the destination? Will Mirth automatically parse the ACK and determine that there was an error?
I had thought that I needed some kind of transformer on the destination (called 'SOAP') and use something along the lines of:
var xml = responseMap.get('SOAP').getMessage();
and then extract the ProcessMessageResponse element but responseMap.get('SOAP') returns null so that seems the wrong approach.
I've now solved part of this thanks to an answer on the Mirth forums.
To summarize, I use the following postprocessor to extract the ack and update the status:
var s = new Namespace('http://schemas.xmlsoap.org/soap/envelope/');
var bw = new Namespace('http://www.bluewire-technologies.com/webservices');
var response = new XML($r('SOAP').getMessage());
var ack = new XML(SerializerFactory.getHL7Serializer().toXML(response.s::Body.bw::ProcessMessageResponse.bw::ProcessMessageResult.toString()));
var ackCode = ack.MSA['MSA.1']['MSA.1.1'].toString();
if(ackCode == 'AE')
{
var errorMessage = ack.MSA['MSA.3']['MSA.3.1'].toString();
var messageController = com.mirth.connect.server.controllers.DefaultMessageObjectController.create();
var channelStatisticsController = com.mirth.connect.server.controllers.DefaultChannelStatisticsController.create();
messageObject.getContext().put("replace", "true"); // yuk - this is to make setError below work.
messageController.setError(messageObject, null, errorMessage, null, null);
channelStatisticsController.decrementSentCount(new java.lang.String(channelId));
}
Not pretty, but it works...