How to apply a prefix to all Child elements in SOAP message - java

While structuring SOAP message having an issue with adding prefix to the subelement of ext:msg_LocationDetails element using QName and javax.xml.soap.Name
I'm using javax.xml.soap.SOAPFactory
When i try to use QName mag = new QName("","Messages","ext");
(new QName(namespaceURI, localPart, prefix))
Exception in thread "main" org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
at com.sun.org.apache.xerces.internal.dom.ElementNSImpl.setName(ElementNSImpl.java:149)
at com.sun.org.apache.xerces.internal.dom.ElementNSImpl.<init>(ElementNSImpl.java:80)
at com.su
It gives the above exception.
SOAPBody soapBody = soapEnvelope.getBody();
soapBody = soapMessage.getSOAPBody();
soapBody.setPrefix("soapenv");
// To add some element
SOAPFactory soapFactory = SOAPFactory.newInstance();
Name bodyName = soapFactory.createName("msg_LocationDetails");
SOAPBodyElement locationDetails = soapBody.addBodyElement(bodyName);
locationDetails.setPrefix("ext");
QName mag = new QName("","Messages","ext");
SOAPElement messages = locationDetails.addChildElement(mag);
//SOAPElement messages = locationDetails.addChildElement("Messages");
//messages.addNamespaceDeclaration("fir", "");
//SOAPElement message = messages.addChildElement("message");
Below is the SOAP message
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ext="http://extdomain.com/">
<soapenv:Header/>
<soapenv:Body>
<ext:msg_LocationDetails>
<ext:Messages>
<ext:Message>
<ext:Location>GSA</ext:Location>
<ext:LocCode>Unit</ext:LocCode>
<ext:LocID>00004</ext:LocID>
<ext:SystemID>TSKSLSLSJJ</ext:SystemID>
<ext:Status>
<ext:ID>4</ext:ID>
<ext:Name>PENDING</ext:Name>
</ext:Status>
</ext:Message>
</ext:Messages>
</ext:msg_LocationDetails>
</soapenv:Header/>
</soapenv:Body>

Related

Soap Request using java - Request call format issue

I'm trying to make a SOAP call with this Java code:
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("UserAuthentication", serverURI);
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("UserAuthentication", "UserAuthentication");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("user_name", "UserAuthentication");
soapBodyElem1.addTextNode("pqr#xyz.com");
SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("password", "UserAuthentication");
soapBodyElem2.addTextNode("123");
soapMessage.saveChanges();
The required format of SOAP call (I'm trying to generate) 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>
<UserAuthentication xmlns="http://tempuri.org/">
<user_name>string</user_name>
<password>string</password>
</UserAuthentication>
</soap:Body>
</soap:Envelope>
But the actual call generated by my code doesn't match the required format and is rejected at the receiving end, and I'm trying to figure out why and how to fix it:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:UserAuthentication="http://XXX.XXX.XXX.XXX:XXXX/Logininfo.asmx?op=UserAuthentication">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<UserAuthentication:UserAuthentication>
<UserAuthentication:user_name>pqr#xyz.com</UserAuthentication:user_name>
<UserAuthentication:password>123</UserAuthentication:password>
</UserAuthentication:UserAuthentication>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
What's the error message from the receiving end?
In any case, the namespaces for the UserAuthentication elements differ.
Expected: http://tempuri.org/
Actual: http://XXX.XXX.XXX.XXX:XXXX/Logininfo.asmx?op=UserAuthentication
envelope.addNamespaceDeclaration("UserAuthentication", serverURI);
Why are you adding that namespace when given you desired request it is not needed?
Try removing that line. Then this one:
SOAPElement soapBodyElem = soapBody.addChildElement("UserAuthentication", "UserAuthentication");
Make it:
QName bodyName = new QName("http://tempuri.org/",
"UserAuthentication", "m");
SOAPElement soapBodyElem = soapBody.addChildElement(bodyName);

How is a SOAP response treated different in Java 8 vs Java 6?

Have some legacy code that works with Java 6 but not fully with Java 8. It sends a SOAP request and reads the response. When using Java 8, the response is not correctly parsed and the code returns a failed result.
Here is a simplified version of the code, I have cut out most of the request building code and changed server names and the like. Please pardon any typos.
try {
// Init the factories
SOAPConnectionFactory SOAPConnFac = SOAPConnectionFactory.newInstance();
SOAPFactory SOAPFac = SOAPFactory.newInstance();
MessageFactory MessageFac = MessageFactory.newInstance();
// Create the SOAP Connection
SOAPConnection SOAPConn = SOAPConnFac.createConnection();
// Build the SOAP request message
SOAPMessage SOAPRequestMsg = MessageFac.createMessage();
// Add info to the MIME header for .NET compatibility
MimeHeaders hd = SOAPRequestMsg.getMimeHeaders();
hd.addHeader("SOAPAction", "http://www.mysever.com/respond");
// Remove the SOAP message header, it is not needed in this case
SOAPHeader SOAPRequestHeader = SOAPRequestMsg.getSOAPHeader();
SOAPRequestHeader.detachNode();
// Build the SOAP body main element CheckIt
SOAPBody SOAPRequestBody = SOAPRequestMsg.getSOAPBody();
javax.xml.soap.Name nameRequestBody = SOAPFac.createName("CheckIt", "", "http://www.myserver.com/");
SOAPBodyElement sbeRequestBodyEle = SOAPRequestBody.addBodyElement(nameRequestBody);
// Add all child elements to the CheckIt element
SOAPElement seNameNode = sbeRequestBodyEle.addChildElement("Name");
seNameNode.addChildElement("FirstName").addTextNode("mary");
seNameNode.addChildElement("LastName").addTextNode("smith");
sbeRequestBodyEle.addChildElement("ID").addTextNode("3423");
URL urlWebService = new URL ("http://webserver/BGC/");
// Send the SOAP request message and get back the SOAP response message
SOAPMessage SOAPResponseMsg = SOAPConn.call(SOAPRequestMsg, urlWebService);
SOAPConn.close();
// Pull out the SOAP response body
SOAPBody SOAPResponseBody = SOAPResponseMsg.getSOAPBody();
// Check for SOAP faults
if (SOAPResponseBody.hasFault()) {
SOAPFault newFault = SOAPResponseBody.getFault();
strStatus = "SOAP FAULT:<br>";
strStatus += "<br>code = " + newFault.getFaultCodeAsName();
strStatus += "<br>message = " + newFault.getFaultString();
strStatus += "<br>actor = " + newFault.getFaultActor()+"<br>";
boolOK = false;
} else {
// Pull the CheckProspectResponse element out of the SOAP response body
javax.xml.soap.Name nameResponseBody = SOAPFac.createName("CheckResponse", "", "http://www.mysever.com/");
Iterator iterElement = SOAPResponseBody.getChildElements(nameResponseBody);
if (iterElement.hasNext()){
SOAPBodyElement sbeResponseBodyEle = (SOAPBodyElement) iterElement.next();
// Check for success or failure
String strResultMsg = ((sbeResponseBodyEle.getValue() == null) ? sbeResponseBodyEle.toString() : sbeResponseBodyEle.getValue());
strStatus = "Check response came back from webserver as *" + strResultMsg + "*<br>";
boolOK = (strResultMsg.trim().toUpperCase().indexOf("SUCCESS") > 0);
} // End if (iterElement.hasNext())
} // End if (SOAPResponseBody.hasFault())
} catch(Exception e) {
strStatus = "Error : "+((e.getMessage() != null) ? e.getMessage() : e.toString());
boolOK = false;
} // End try
It seems that when pulling elements out of the response, it gets an empty set.
Iterator iterElement = SOAPResponseBody.getChildElements(nameResponseBody);
Returns a set of null elements. Not a null itself, the set has at least one member but that member is null. It should have a value of "SUCCESS" but it's null. I have looked at the full response and it looks fine, everything is there and it works with Java 6, just not with Java 8. A typical, successful response looks like this:
<?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:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<CheckResponse xmlns="http://www.mysever.com/">
<CheckResult>SUCCESS</CheckResult>
</CheckResponse>
</soap:Body>
</soap:Envelope>
UPDATE
I have found a way around my problem, using getTextContent I get the correct data, or at least the data I expect to get. Given the above SOAP response, Java 8 returns the following for the given method call:
getValue = null
getNodeValue = null
getLocalName = CheckResponse
getNodeName = CheckResponse
getNamespaceURI = http://www.mysever.com/
getPrefix = null
getTextContent = SUCCESS
Acording to both Java 6 and Java 8 docs, the returned value for getValue should be "SUCCESS" in this case. Which is true for Java 6 but false for Java 8.
Any ideas on why this method works with Java 6 but not with Java 8? Is this a bug?

Add namespace prefix Axis2

This is envelope which i wanna to send to service:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<sear:searchUrls>
<sear:in0>Safeway, 200 S. 3rd St, Renton, WA</sear:in0>
</sear:searchUrls>
</soapenv:Body>
</soapenv:Envelope>
And this is code to construct it:
SOAPFactory fac = OMAbstractFactory.getSOAP12Factory();
SOAPEnvelope envelope = fac.getDefaultEnvelope();
OMNamespace omNs = fac.createOMNamespace("http://schemas.xmlsoap.org/soap/envelope/", "soapenv");
OMNamespace ns1 = fac.createOMNamespace("http://search", "sear");
envelope.setNamespace(omNs);
OMNamespace ns = fac.createOMNamespace("", "")
OMElement method = fac.createOMElement("sear:searchUrls", ns);
OMElement value = fac.createOMElement("sear:in0", ns);
value.setText("Safeway, 200 S. 3rd St, Renton, WA");
method.addChild(value);
envelope.getBody().addChild(method);
But my namespace prefix "sear" is not defined.
How can I set it in code to get
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sear="http://search">
in XML?
envelope.addNamespaceDeclaration("sear", "http://search");
OMNamespace xsi = soapFactory.createOMNamespace(
Constants.URI_DEFAULT_SCHEMA_XSI,
Constants.NS_PREFIX_SCHEMA_XSI);
envelope.declareNamespace(xsi);
Do you have the WSDL and know the end point url ?
You can generate the client side code using the wsdl2java convertor.
More information at http://axis.apache.org/axis2/java/core/docs/userguide-creatingclients.html#choosingclient

Unable to parse content type of return SOAP request (java)

I'm trying to send-retrive message from server by SOAP...
but
soapConnection.call( soapMessage, endpoint )
returns:
com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to parse content type: null
Hereis my code:
String url = "https://pubcommission.api.cj.com/wsdl/version2/publisherCommissionServiceV2.wsdl";
String method = "findPublisherCommissionDetails";
SOAPConnection soapConnection = SOAPConnectionFactory.newInstance().createConnection();
SOAPFactory soapFactory = SOAPFactory.newInstance();
MessageFactory messageFactory = MessageFactory.newInstance();
// Create a message from the message factory.
SOAPMessage soapMessage = messageFactory.createMessage();
// creat a SOAP part have populate the envelope
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.setEncodingStyle( SOAPConstants.URI_NS_SOAP_ENCODING );
// remove all header information from envelope
envelope.getHeader().detachNode();
// create a SOAP body
SOAPBody body = envelope.getBody();
Name babelFishRequestName = envelope.createName( method, "ns1", "http://api.cj.com" );
SOAPBodyElement soapMethod = body.addBodyElement( babelFishRequestName );
// add elements translationmode and sourcedata to BabelFishRequest
soapMethod.addChildElement( soapFactory.createElement( "developerKey", "ns1", "http://api.cj.com" ).addTextNode( "nevermind" ) );
soapMethod.addChildElement( soapFactory.createElement( "originalActionIds", "ns1", "http://api.cj.com" ).addTextNode( "1234567" ) );
// set the saves into the structure
soapMessage.saveChanges();
// output the message
System.out.println( "\n============= start request msg ==========\n" );
soapMessage.writeTo( System.out );
System.out.println( "\n============= end request msg ==========\n" );
URLEndpoint endpoint = new URLEndpoint(url);
System.out.println( "\nSending message to URL: " + endpoint.getURL() );
// now make that call over the SOAP connection
SOAPMessage reply = soapConnection.call( soapMessage, endpoint );
I tried utility 'Membrane' to check result and got the following result (RAW):
HTTP/1.0 500 Internal Server Error
Server: Resin/3.1.8
Content-Type: text/xml; charset=UTF-8
Date: Wed, 08 Feb 2012 10:45:47 GMT
X-Cache: MISS from proxy.myserver.com
X-Cache-Lookup: MISS from proxy.myserver.com:3128
Via: 1.0 proxy.myserver.com (squid/3.1.18)
Connection: close
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Action id specified does not match your account: 1234567</faultstring></soap:Fault></soap:Body></soap:Envelope>
Don't know about that error. If using JAX-WS API is an option for you, this is the way to go:
Use wsimport tool to generate client objects:
wsimport.bat -keep -d "\ProjectDir\src" https://pubcommission.api.cj.com/wsdl/version2/publisherCommissionServiceV2.wsdl
This will generate everything you need to call the web service:
com.cj.api
com.cj.domain.transaction
com.cj.service.transaction
In the api package you find the service and port objects, the latter allows you to access the web service methods:
PublisherCommissionServiceV2 service = new PublisherCommissionServiceV2();
PublisherCommissionServiceV2PortType port = service.getPublisherCommissionServiceV2HttpPort();
port.findPublisherCommissionDetails("key", "id");
This will give you a nice not authenticated: key message from the web service.

Java SOAP - Need help on Body and ChildElement manipulation

I'm trying to write some code in java to learn more about coding with WSDL and SOAP.
For example given :'<'to:checkAccount xmlns:to="http://foo">
'<'to:id> test '<'/to:id>
'<'to:password> test '<'/to:password>
'<'to:checkAccount >"
'<'element name="checkAccountResponse">
'<'complexType>
'<'sequence>
'<'element name="checkAccountReturn" type="impl:account"/>
'<'/sequence>
'<'/complexType>
'<'/element>
'<'complexType name="account">
'<'sequence>
'<'element name="active" type="xsd:boolean"/>
'<'element name="name" type="xsd:string"/>
'<'/sequence>
'<'/complexType>
my code looks like this at the moment:
//create the message
String endpoint = "http://foo/someAPI";
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPHeader header = message.getSOAPHeader();
//adding to the body
SOAPBody body = message.getSOAPBody();
SOAPFactory soapFactory = SOAPFactory.newInstance();
Name bodyName = soapFactory.createName("checkAccount","to","http://foo");
SOAPElement bodyElement = body.addBodyElement(bodyName);
//add the ID child elements
soapFactory = SOAPFactory.newInstance();
Name childName = soapFactory.createName("id","to","http://foo");
SOAPElement symbol = bodyElement.addChildElement(childName);
symbol.addTextNode("test");
//add password child element
soapFactory = SOAPFactory.newInstance();
childName = soapFactory.createName("password","to","http://foo");
symbol = bodyElement.addChildElement(childName);
symbol.addTextNode("test");
//call and get the response
SOAPMessage response = sc.call(message,endpoint);
//print the response
SOAPBody responseBody = response.getSOAPBody();
java.util.Iterator iterator = responseBody.getChildElements(bodyName);
.
.
.
//the response is blank so trying to iterate through it gives the exception
I run this and i get nothing in return , just blank. I know my endpoint is correct , as well as the checkAccount ,id and password since I've tested it in xmlSpy and it returns account status.
It has to be the way I'm trying to get the response. Can someone please give me a hint?
This is how I would do it.
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
SOAPBody body = message.getSOAPBody();
SOAPElement checkAccEl = body
.addChildElement("checkAccount", "to", "http://foo");
SOAPElement idEl = checkAccEl
.addChildElement("id", "to", "http://foo");
idEl.addTextNode("test");
SOAPElement passwordEl = checkAccEl
.addChildElement("password", "to", "http://foo");
passwordEl.addTextNode("test");
// print out the SOAP Message. How easy is this?!
ByteArrayOutputStream out = new ByteArrayOutputStream();
message.writeTo(out);
System.out.println(out.toString());
The first time you use the namespace 'to=http://foo' it is automatically declared on the element - checkAccount in this case. When you use the same namespace again, the XML won't need to declare it again, but will use the prefix.
The output looks like:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<to:checkAccount xmlns:to="http://foo">
<to:id>test</to:id>
<to:password>test</to:password>
</to:checkAccount>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Which is what you want I think

Categories