Java SOAP - Need help on Body and ChildElement manipulation - java

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

Related

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

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>

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 to add child element in soap header in java

How to add child element in soap header in java spring webservice.
I have tried two approach but nothing is working please suggest me what need to be done?
first approach :-
soapHeaderString.append("<tem:Culture>en_Us</tem:Culture><tem:AgentCode>PumpkinSafari</tem:AgentCode><tem:PartnerID></tem:PartnerID><tem:Password>PMP22#in</tem:Password>");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// Here we create a Source Tree
StringSource stringSource = new StringSource(soapHeaderString.toString());
transformer.transform(stringSource, soapHeader.getResult());
but it is giving me error
The prefix "tem" for element "tem:Culture" is not bound.
2nd Approach :-
SoapHeaderElement headerElement=soapMessage.getSoapHeader().addHeaderElement(new QName("http://tempuri.org/", "SOAPHeaderAuth","tem"));
headerElement.setText(soapHeaderString.toString());
It produce unescaped sequqnce so service provider give error as it was not able to understand the request.
Please help me what need to be done to solve the problem.
Yes, in my case too it prompts the same error, The prefix "username" for element "wsse:username" is not bound. I tried doing everything to add namespace declaration. But, it doesn't worked!
"Finally", I was able to do it last night with a workaround, converting some way from Spring org.springframework.ws.soap.SoapHeader to javax.xml.soap.SOAPHeader. And no issues now!
SOAPMessage soapMessage = ((SaajSoapMessage) message).getSaajMessage();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPHeaderElement security = header.addHeaderElement(new QName(SCHEMA, "Security", SCHEMA_PREFIX));
SOAPElement usernameToken = security.addChildElement("UsernameToken", SCHEMA_PREFIX);
SOAPElement usernameElement = usernameToken.addChildElement("Username", SCHEMA_PREFIX);
SOAPElement passwordElement = usernameToken.addChildElement("Password", SCHEMA_PREFIX);
usernameElement.setTextContent(username);
passwordElement.setTextContent(password);
Through this I was able to add namespace declarations to spring soap header child elements!
JAX-WS Users
I would recommend using a message handler:
http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client
Spring Web Services Users
A similar concept exists:
http://arcanetechnotes.blogspot.com/2008/12/modifying-soap-headers-with-spring-web.html
The question states that it cannot understand the tem namespace, so perhaps register the namespace in the header:
soapHeader.addNamespaceDeclaration("tem", "http://whatever.namespace.com/");
Use "header=true" property in webparam
Like
#WebMethod(operationName = "someMethod")
public String someMethod(#WebParam(name = "yourBeanObj") YourBeanObjClass yourBeanObj,
#WebParam(header = true, mode = WebParam.Mode.IN, name = "username") String userName,
#WebParam(header = true, mode = WebParam.Mode.IN, name = "password") String pwd) {
//todo stuff
}
As per above example "yourBeanObj" wil be added into soap body, "username" and "password" are add in soap header.

Get elements of SOAP response

When I send a SOAP request using SAAJ API, I would receive a large SOAP response, in which I need to search for some nodes.
I am using following code but it just show the name of first node of body (HotelListResponse which has many children) and I have noticed that the loop just iterates once, (as shown in commented section).
In short: I need to know how to search for some nodes (preferably by their name) in a variable which its type is SOAPMessage. Thanks
SOAPMessage sm = response; //this is the response
sm.writeTo(System.out); //response is shown successfully in console
SOAPBody ReBody = sm.getSOAPBody();
Iterator sentIt = ReBody.getChildElements(); //create an iterator on elements
int counter=0;
while(sentIt.hasNext())
{
SOAPBodyElement sentSBE = (SOAPBodyElement)sentIt.next();
Iterator sentIt2 = sentSBE.getChildElements();
SOAPElement sentSE = (SOAPElement)sentIt2.next();
String sentID = sentSE.getNodeName(); //result is HotelListResponse
counter++;
//System.out.println("sentID:"+sentID);
}
System.out.println("counter"+counter); //result is 1

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.

Categories