Camel SoapJaxbDataFormat with multiple namespace(s) - soap

i have a need to marshal inbound xml into a SOAP data format within my Camel route for use in data transformation, i have encounters an issue where the inbound message contains a namespace defined in an element other then root which leads to parts of the message being lost or incorrectly formatted.
How would i go about defining a SoapJaxbDataFormat for my message with multiple namespaces?
Example Camel Route i have been using to track down my issues
import com.example.ws.ExampleDataResponse;
import javax.xml.namespace.QName;
import org.apache.camel.dataformat.soap.name.QNameStrategy;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.dataformat.SoapJaxbDataFormat;
public class ExampleCamelRoute extends RouteBuilder {
// defining my SOAP format
SoapJaxbDataFormat soapExampleDataResponse;
#Override
public void configure() throws Exception {
// Setting my data format
soapExampleDataResponse = new SoapJaxbDataFormat(ExampleDataResponse.class.getPackage().getName(), new QNameStrategy(new QName("http://ws.example.com","exampleDataResponse")));
// Enter route definition here
from("amqp:queue:{{ExampleDataResponse.queue}}").routeId("ExampleDataResponse")
.streamCaching()
.log("Data receved from example")
// view the orignal message
.to("file:C:/Camel_Target?fileName=ExampleData_Orignal.xml", "direct:writeMarshaledData", "direct:writeUnMarshaledData");
from("direct:writeMarshaledExampleData").routeId("writeMarshaledExampleData")
.marshal(soapExampleDataResponse)
// view the marshaled message
.to("file:C:/Camel_Target?fileName=ExampleData_marshal.xml");
from("direct:writeUnMarshaledExampleData").routeId("writeUnMarshaledExampleData")
.unmarshal(soapExampleDataResponse)
// view the unmarshaled message
.to("file:C:/Camel_Target?fileName=ExampleData_UnMarshaled.xml");
}
}
Example of the original inbound xml message written out to file, i will need to marshal / unmarshal this data to a SOAP format
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<exampleDataResponse xmlns="http://ws.example.com">
<exampleDataReturn>
<name>user1</name>
<number>8797877979877</number>
<contacts>
<ns1:name xmlns:ns1="http://contact.ws.example.com">contact1</ns1:name>
<ns2:number xmlns:ns2="http://contact.ws.example.com">4545664464564</ns2:number>
</contacts>
</exampleDataReturn>
</exampleDataResponse>
</soapenv:Body>
</soapenv:Envelope>
Example marshaled data written out to file
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ns2:Envelope xmlns:ns5="http://data.contact.ws.example.com" xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns4="http://contact.ws.example.com" xmlns:ns3="http://ws.example.com">
<ns2:Body>
<ns3:exampleDataResponse>4545664464564</ns3:exampleDataResponse>
</ns2:Body>
</ns2:Envelope>
As you can see the data here is incorrect.
Example of unmarshaled message written out to file
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ns2:exampleDataResponse xmlns="http://contact.ws.example.com" xmlns:ns2="http://ws.example.com"/>
As you can see the data here is incorrect, i use SoapJaxbDataFormat's alot in my camel routes and have not encounters this issue before, stranger still the route doesn't error.
Thank you in advanced for any help in how i can properly define this format.

Related

SOAP request with certain tags without namespace

Would be the following SOAP request valid according to the standard?
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns2:ServiceReq xmlns:ns2="http://www.tibco.com/service" xmlns:ns1="http://www.tibco.com/framework">
<ns1:HeaderIn>
<ns1:countryISO>FR</ns1:countryISO>
<ns1:callerDateTime>2021-11-26T15:50:08.742Z</ns1:callerDateTime>
</ns1:HeaderIn>
<ns2:request>
<entete>
<profile>Default</profile>
</entete>
<input>
<type>W</type>
<codeRegion>X</codeRegion>
</input>
</ns2:request>
</ns2:ServiceReq>
</soapenv:Body>
</soapenv:Envelope>
I am not sure because certain tags don't have a namespace
There are multiple levels of valid here:
Is it a valid SOAP message as per the SOAP standard? Yes. The SOAP envelope and body tags seem valid.
Is it a valid XML format? Yes, it's a well formed XML file.
Are those elements without a namespace prefix valid? Yes. Elements can be in a default namespace or in no namespace at all.
Is the actual content of the body a valid messages? You can only tell if you verify the message you posted against the expected message as defined in the WSDL file of the web service.
All the elements in the body of the SOAP message should belong to specific namespaces, but sometimes a developer forgets to add a namespace annotation on the element, or copy-pastes something from some place else, or whatever, and you end up with weird looking XMLs like that. The service works and the message is correctly parsed, but it just looks funny.

Why there are different request definition for one wsdl

I have been provided a WSDL by client at the beginning of the project, I ended up creating a request and response objects for given WSDL using SOAP UI, where the request object would look as follows,
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:def="http://DefaultNamespace">
<soapenv:Header/>
<soapenv:Body>
<def:someOperation soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<in0 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">SOME_DATA</in0>
</def:someOperation>
</soapenv:Body>
</soapenv:Envelope>
But when the actual request coming from the production environment for the same wsdl is,
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<someOperation xmlns="urn:SOMEService">
<in0>SOME_DATA</in0>
</someOperation>
</soap:Body>
</soap:Envelope>
If you observed the name spaces are the same but it does has difference for names like in 1st request its <soapenv:Envelope and same in the 2nd request is <soap:Envelope in each node of xml, the definition of operation is also different in both the request in 1st it is,
<def:someOperation soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<in0 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">SOME_DATA</in0>
</def:someOperation>
and in 2nd it is,
<someOperation xmlns="urn:SOMEService">
<in0>SOME_DATA</in0>
</someOperation>
I do not know why the interpretation is different, and is it safe to have to change from 1st to 2nd.
IN both the cases actual operation is working fine I do not have any issues with that, it is just cant able to figure out reason of difference.
Could somebody please assist me with this or any direction to a document which could clarify my doubt would be great.
it does has difference for names like in 1st request its <soapenv:Envelope and same in the 2nd request is <soap:Envelope in each node of xml
Here soapenv and soap are local prefix names of namespace=http://schemas.xmlsoap.org/soap/envelope/. Hence, logically both are same and has no difference.
the definition of operation is also different in both the request in 1st v/s 2nd
In case of 1st, def:someOperation XML nodes belongs to namespace = xmlns:def="http://DefaultNamespace"
And in 2nd case, name space "urn:SOMEService" is directly defined with XML Nodes So
if DefaultNamespace is exactly same as SOMEService, the it means both of the XML Operation XMLs are same.
Hence,
soapenv v/s soap are same in your case.
Operations, you could conclude based on actual value of SOMEService v/s DefaultNamespace.
Hope it helps.

javax.xml.soap.SOAPException: InputStream does not represent a valid SOAP 1.1 Message

I am consuming a SOAP API. The XML response I receive is surrounded with a 'soap envelope' - so I need to remove or parse past that wrapper before I can process the XML. I've taken the below approach with other endpoints (so the code is sane, at least) but with this particular endpoint, I get errors.
The error I'm encountering is:
SEVERE: SAAJ0304: InputStream does not represent a valid SOAP 1.1
Message
This is the code I am using to remove the Soap Wrapper:
String soapResponse = getSoapResponseFromApi();
ByteArrayInputStream inputStream = new ByteArrayInputStream(soapResponse.getBytes());
SOAPMessage message = MessageFactory.newInstance().createMessage(null, inputStream);
Document doc = message.getSOAPBody().extractContentAsDocument(); // <-- error thrown here
//unmarhsall the XML in 'doc' into an object
//do useful stuff with that object
here is the XML I am receiving back (the contents of soapResponse in the code above)
<?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>
<XMLContentIActuallyWant xmlns="http://my-url.com/webservices/">
<!-- Useful stuff here -->
</XMLContentIActuallyWant >
</soap:Body>
</soap:Envelope>
I discovered the solution as I was preparing this question.
Soap versions have different formatting. The SoapMessage library was defaulting to soap 1.1 - but the contents of the response I was receiving was soap 1.2.
I could see this when I inspected the full request that was being sent, in order to receive the response noted above - it looked like this:
<?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:Body>
<!-- xml content here -->
</soap12:Body>
</soap12:Envelope>
the soap12 part highlights that it is requesting soap 1.2.
so although the response doesn't contain the '12' - the response is also in 1.2.
So we need to tell SoapMessage to use 1.2 instead of the default (1.1 in my case).
I did this by modifying my code above like so:
Before:
SOAPMessage message = MessageFactory.newInstance().createMessage(null, inputStream);
After:
SOAPMessage message = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage(null, inputStream);
It's worth noting that other endpoints of the same API served SOAP 1.1 - which is why this error was so confusing for me. I was doing the same thing and getting different results.

Xml parsing for soap response

how to parse soap response data
<?xml version="1.0" encoding="utf-8" ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sqltypes=
"http://schemas.microsoft.com/SQLServer/2001/12/SOAP/types"
xmlns:sqlmessage=
"http://schemas.microsoft.com/SQLServer/2001/12/SOAP/
types/SqlMessage"
xmlns:sqlresultstream=
"http://schemas.microsoft.com/SQLServer/2001/12/SOAP/types
/SqlResultStream"
xmlns:tns="http://server/nwind2/soap"
<SOAP-ENV:Body>
<tns:MethodNameResponse>
<tns:OutputParam>Error Code 1152</tns:OutputParam>
</tns:MethodNameResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I expected the response data will be simple xml format, but the response is in soap-env.
how to parse the soap envelop xml data?
Is in soap-envelop format xml parsing is same has simple xml data parse?
example:Simple XML
<?xml version="1.0" encoding="utf-8" ?>
<error >Error Code 1152 </error>
#all Any one advice me how to parse this kind on xml
Thanks in advance.
This is wsdl web services. You can use http://sudzc.com/ which will generate Objective C stubs for you.

Is it possible to add an attribute to an XML Root using nusoap's call() function?

I am creating a class that will be utilizing the Fedex Web Services. I am attempting to communicate through the nusoap php class's nosoapclient() function, passing it a wsdl file. It seems Fedex requires a namespace attribute in the document root of a request.
I can use nusoap's call() function and pass it an XML string as the PARAMETER agrument which WILL WORK properly. I would rather pass an array through as the PARAMETER argument, and this is where I am running into an issue.
Is it possible to pass an array through nusoap's call() function and also include a namespace attribute in the root?
FEDEX RateRequest PHP exerpt
The following is to give an idea of what I am trying to do and not actual code
$client = new nusoapclient('RateRequest_v9.wsdl',true);
//Thought this would work but to no avail.
//$request_array is a multi-associative array with keys as required XML tag names and values as the tags inner value, did not include as it is irrelevant to this problem
//$root_attr = array('xmlns'=>'http://fedex.com/ws/rate/v9');
//$parameters = array('RateRequest'=>new soapval('RateRequest',false,$request_array,false,false,$root_attr));
$parameters = array('RateRequest'=>$request_array);
//Have tried with and without the third argument - which is the for the namespace
$response = $client->call('getRates',$parameters,'http://fedex.com/ws/rate/v9');
FEDEX RateRequest XML excerpt
The following is not the full XML (look at the RateRequest tag toward the end to see the difference)
INCORRECT FORMAT
<?xml version="1.0" encoding="ISO-8859-1"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="http://fedex.com/ws/rate/v9"><SOAP-ENV:Body><RateRequest>...</RateRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
CORRECT FORMAT
<?xml version="1.0" encoding="ISO-8859-1"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="http://fedex.com/ws/rate/v9"><SOAP-ENV:Body><RateRequest xmlns="http://fedex.com/ws/rate/v9">...</RateRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
My apologies in advance if I have missed this conversation elsewhere but I have been scouring the net and trying everything I could think of to make it work, if its not possible any suggestions? Thank you in advance for your assistance.