How to change namespace prefix in SOAP webservice request created with SOAPMessage? - java

When I create my SOAP request using the javax.xml.soap.SOAPMessage class, I get a namespace prefix in my XML like <SOAP-ENV:Envelope>.
Is there a simple way to change the namespace prefix to <soapenv:Envelope>?

The XML namespace prefix should not matter as long as you are calling a well behaved web service. So SOAP-ENV:, soapenv:, or whatever: are basically the same thing as long as they both refer to the same namespace.
With that being said, if you really need to do this for some reason, here is some minimally working code. I'm calling this service.
package soap;
import java.io.IOException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
public class Client {
public static void main(String[] args) throws SOAPException, IOException {
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
MimeHeaders mimeHeader = message.getMimeHeaders();
mimeHeader.setHeader("SOAPAction", "http://tempuri.org/Add");
SOAPBody body = message.getSOAPBody();
SOAPHeader header = message.getSOAPHeader();
QName bodyName = new QName("http://tempuri.org/", "Add", "tmp");
SOAPBodyElement bodyElement = body.addBodyElement(bodyName);
SOAPElement intA = bodyElement.addChildElement(new QName("http://tempuri.org/", "intA", "tmp"));
intA.addTextNode("123");
SOAPElement intB = bodyElement.addChildElement(new QName("http://tempuri.org/", "intB", "tmp"));
intB.addTextNode("456");
message.writeTo(System.out);
System.out.println();
// -----------------> Now changing the prefix before making the call
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
envelope.removeNamespaceDeclaration(envelope.getPrefix());
String prefix = "soapenv";
envelope.addNamespaceDeclaration(prefix, "http://schemas.xmlsoap.org/soap/envelope/");
envelope.setPrefix(prefix);
header.setPrefix(prefix);
body.setPrefix(prefix);
// <---------------- done changing the prefix
message.writeTo(System.out);
System.out.println();
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection connection = soapConnectionFactory.createConnection();
URL endpoint = new URL("http://www.dneonline.com/calculator.asmx");
SOAPMessage response = connection.call(message, endpoint);
connection.close();
response.writeTo(System.out);
}
}
I've printed the request message before and after the transformation. The output is as follows (formatting not included :D):
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<tmp:Add xmlns:tmp="http://tempuri.org/">
<tmp:intA>123</tmp:intA>
<tmp:intB>456</tmp:intB>
</tmp:Add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<tmp:Add xmlns:tmp="http://tempuri.org/">
<tmp:intA>123</tmp:intA>
<tmp:intB>456</tmp:intB>
</tmp:Add>
</soapenv:Body>
</soapenv:Envelope>
<?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>
<AddResponse xmlns="http://tempuri.org/">
<AddResult>579</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>

Related

JAX-WS add Username-Token to SOAP-Header

I have a JAX-WS Client generated from WSDL files.
Setting Headers worked so far with following code:
WSBindingProvider bp = (WSBindingProvider) port;
bp.setOutboundHeaders(
Headers.create(new QName("http://schemas.xmlsoap.org/ws/2005/08/addressing", "To", "wsa"), "--To--"),
Headers.create(new QName("http://schemas.xmlsoap.org/ws/2005/08/addressing", "Action", "wsa"), "--Action--"),
Headers.create(new QName("http://schemas.xmlsoap.org/ws/2005/08/addressing", "MessageID", "wsa"), UUID.randomUUID().toString())
);
Which produces (as desired) the following XML snippet:
<S:Header>
<To
xmlns="http://schemas.xmlsoap.org/ws/2005/08/addressing">--to--
</To>
<Action
xmlns="http://schemas.xmlsoap.org/ws/2005/08/addressing">--action--
</Action>
<MessageID
xmlns="http://schemas.xmlsoap.org/ws/2005/08/addressing">fe1b400a-e724-4486-8618-b1d36a0acbbb
</MessageID>
</S:Header>
But I need the following chained Tags, which I couldn't acheive with Headers.create(...):
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="PartnerId" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>--username--</wsse:Username>
</wsse:UsernameToken>
</wsse:Security>
Any ideas how I can add this to the header?
The following code works for me:
private static final String SCHEMA = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
private static final String SCHEMA_PREFIX = "wsse";
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
// Create a SOAP header
try {
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPHeader header = soapEnvelope.getHeader();
// Add the security SOAP header element
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);
Name typeName = soapEnvelope.createName("type");
passwordElement.addAttribute(typeName, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
usernameElement.setTextContent(USERNAME);
passwordElement.setTextContent(PASSWORD);
((WSBindingProvider) webServicePort).setOutboundHeaders(Headers.create(security));
} catch (SOAPException e) {
logger.severe("Error setting SOAP header");
e.printStackTrace();
}
The XML is as follows:
<?xml version="1.0" encoding="utf-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<env:Header>
<wsse:Security env:mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username>username</wsse:Username>
<wsse:Password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</env:Header>
<env:Body>
...

Modify Soap header in SoapHandler

I am trying to modify a soap header, and i want header to be like this
<soapenv:Header xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns:authnHeader soapenv:mustUnderstand="0" xmlns:ns="http://webservices.averittexpress.com/authn">
<Username>xxxxxxxx</Username>
<Password>xxxxxxxx</Password>
</ns:authnHeader>
This is what i have done till now...
SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
header.addAttribute(new QName("xmlns:soapenc"), "http://schemas.xmlsoap.org/soap/encoding/");
header.addAttribute(new QName("xmlns:xsd"), "http://www.w3.org/2001/XMLSchema");
header.addAttribute(new QName("xmlns:xsi"), "http://www.w3.org/2001/XMLSchema-instance");
SOAPElement authnHeader = header.addChildElement("authnHeader", "ns" , "http://webservices.averittexpress.com/authn");
authnHeader.addAttribute(new QName("soapenv:mustUnderstand"), "0");
But I am getting
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 first header.addAttribute.
Please help.
My Import Statements
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
You are getting this error because you are trying to define namespace attributes in the SOAP header. Namespace attributes xmlns must be defined in the SOAP envelope. So the XML SOAP envelope you really want would look something like this:
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header>
<ns:authnHeader soapenv:mustUnderstand="0" xmlns:ns="http://webservices.averittexpress.com/authn">
<Username>xxxxxxxx</Username>
<Password>xxxxxxxx</Password>
</ns:authnHeader>
</soap:Header>
<soap:Body>
<!-- your content goes here -->
</soap:Body>
</soap:Envelope>
According to conventions if your XML does not give a SOAP namespace in the envelope applications may reject your SOAP message.
For reference, I spent about 3 hours trying to find one code example where someone calls header.addAttribute() on a SOAP header, and I could not find even one.
Finally had some luck.
This code works
Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(outboundProperty.booleanValue())
{
try
{
SOAPHeader header = context.getMessage().getSOAPPart().getEnvelope().getHeader();
SOAPFactory soapFactory = SOAPFactory.newInstance();
SOAPElement authnHeader = soapFactory.createElement("authnHeader", "ns", "http://webservices.averittexpress.com/authn");
SOAPElement username = authnHeader.addChildElement("Username");
username.setTextContent("xxxxxxx");
SOAPElement password = authnHeader.addChildElement("Password");
password.setTextContent("xxxxxxx");
header.addChildElement(authnHeader);
}
catch(Exception e)
{
e.printStackTrace();
}
}
After adding header do not forget to save the message
context.getMessage().saveChanges();
or
context.getMessage().writeTo(System.out);
also saves message if any changes are done.

How to create SOAP request with CDATA

I am new to SOAP,I want to create SOAP request,as given below
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<SOAP-ENV:Header/>
<soapenv:Body>
<tem:RequestData>
<tem:requestDocument>
<![CDATA[
<Request>
<Authentication CMId="68" Function="1" Guid="5594FB83-F4D4-431F-B3C5-EA6D7A8BA795" Password="poihg321TR"/>
<Establishment Id="4297867"/>
</Request>
]]>
</tem:requestDocument>
</tem:RequestData>
</soapenv:Body>
</soapenv:Envelope>
Code for creating SOAP request i have found in tutorial
MessageFactory mf = MessageFactory.newInstance();
SOAPMessage sm = mf.createMessage();
SOAPEnvelope envelope = sm.getSOAPPart().getEnvelope();
envelope.addNamespaceDeclaration("soap", "http://schemas.xmlsoap.org/soap/envelope/");
envelope.setPrefix("soapenv");
envelope.setAttribute("xmlns:tem", "http://tempuri.org/");
SOAPBody body = envelope.getBody();
body.setPrefix("soapenv");
SOAPElement requestData = body.addChildElement("RequestData");
requestData.setPrefix("tem");
SOAPElement requestDoc = requestData.addChildElement("requestDocument","tem","http://tempuri.org/");
requestDoc.addTextNode(" <![CDATA[");
SOAPElement request = requestDoc.addChildElement("Request");
SOAPElement authentication = request.addChildElement("Authentication");
authentication.setAttribute("CMId", "68");
authentication.setAttribute("Guid", "5594FB83-F4D4-431F-B3C5-EA6D7A8BA795");
authentication.setAttribute("Password", "poihg321TR");
authentication.setAttribute("Function", "1");
SOAPElement establishment = request.addChildElement("Establishment");
establishment.setAttribute("Id", "4297867");
requestDoc.addTextNode("]]>");
System.out.println("\nSoap Request: \n\n\n"+getMsgAsString(sm));
Output I am getting is when executing the code.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/"><SOAP-ENV:Header/><soapenv:Body><tem:RequestData><tem:requestDocument xmlns:tem="http://tempuri.org/"> <![CDATA[<Request><Authentication CMId="68" Function="1" Guid="5594FB83-F4D4-431F-B3C5-EA6D7A8BA795" Password="poihg321TR"/><Establishment Id="4297867"/></Request>]]></tem:requestDocument></tem:RequestData></soapenv:Body></soapenv:Envelope>
The problem is
<![CDATA[ ]]> is displaying like <![CDATA[ and ]]>
And my Server is not accepting this request.
You need to create and add a CDATASection:
CDATASection cdata =
requestDoc.getOwnerDocument().createCDATASection("<element>text</element>");
requestDoc.appendChild(cdata);
This will produce:
<![CDATA[<element>text</element>]]>

Creating Soap Request with Xml Document in java

I need to make this soap request
<?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>
<Update xmlns="http://tempuri.org/">
<doc>xml</doc>
</Update>
</soap:Body>
</soap:Envelope>
in that <doc>xml</doc> this is the field where i have to add Xml document file but its all time getting String formate. so how to now make this Soap request can anybody give me idea.
I have tried CDATA but at the other end its giving error while giving request.
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://tempuri.org/";
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("tem", serverURI);
SOAPElement sOAPElement = envelope.addChildElement("Update", "tem");
SOAPElement xml_APElement = sOAPElement.addChildElement("doc", "tem");
CDATASection aSection = soapPart.createCDATASection(builder.toString());
xml_APElement.appendChild(aSection);
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "Update");
soapMessage.saveChanges();
System.out.print("Request SOAP Message = ");
soapMessage.writeTo(System.out);

Setting up an XML response for SOAP

I'm having a real hard time with this issue.
Basically I've built a WebService using Java/JAX-WS, this is my Interface
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
#WebService
public interface OperationsInterface {
#WebResult(name = "result")
LoginResponse Login(#WebParam(name = "login") Login login);
#WebResult(name = "result")
String Purchase(#WebParam(name = "purchase") Purchase purchase);
}
Login is just a POJO that contains 2 strings (username and password)
LoginResponse is another POJO, it has this
String status;
int code;
String message;
SubscriptionTier subscriptionTier;
String accountNumber;
String firstName;
String lastName;
Nothing fancy, pretty simple in fact. The request is something like this
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ott="http://ott.amentum.net/">
<soapenv:Header/>
<soapenv:Body>
<ott:Login>
<login>
<username>USERNAME</username>
<password>1234</password>
</login>
</ott:Login>
</soapenv:Body>
</soapenv:Envelope>
And the response comes like this
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:LoginResponse xmlns:ns2="http://ott.amentum.net/">
<result>
<accountNumber>0110000076</accountNumber>
<code>1</code>
<firstName>JOHN</firstName>
<lastName>DOE</lastName>
<message>Login has been successful.</message>
<status>success</status>
<subscriptionTier>
<tier>TVOD</tier>
<tier>CANAL</tier>
<tier>CATCHUP</tier>
</subscriptionTier>
</result>
</ns2:LoginResponse>
</soap:Body>
</soap:Envelope>
As far as I know, this is correct, however, my customer is expecting something like this
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:LoginResponse xmlns:ns2="http://ott.amentum.net/">
<accountNumber>0410089676</accountNumber>
<code>1</code>
<firstName>MARIA DEL CARMEN</firstName>
<lastName>PADILLA MARTIN</lastName>
<message>Login has been successful.</message>
<status>success</status>
<subscriptionTier>
<tier>TVOD</tier>
<tier>CANAL</tier>
<tier>CATCHUP</tier>
</subscriptionTier>
</ns2:LoginResponse>
</soap:Body>
</soap:Envelope>
They want me to remove the result tag, which is the name of the LoginResponse object I created to return the information.
Is there a way to do this?
Thanks in advance

Categories

Resources