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.
Related
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>
Here is my soap web service resposne
<?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<S:Body>
<ns3:getShopInfoResponse xmlns:customns="http://test/" xmlns:ns3="http://service.prasad.com/">
<return>
<code>12345</code>
</return>
</ns3:getShopInfoResponse>
</S:Body>
</S:Envelope
In the above response beside code i want to have the namespace like this
<ns4:code xlmns:ns4="http://code.prasad.com">12345</code> like
,how can i get this
Below is the code which m using
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.prasad.service;
import com.prasad.code.Code;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
/**
*
* #author dell
*/
#WebService
#SOAPBinding(style = SOAPBinding.Style.RPC)
public class ShopInfo {
#WebMethod
public Code getShopInfo(String name){
Code code = new Code();
code.setCode("12345");
if ("shop".equalsIgnoreCase(name)){
code.setCode("Test Mart");
}
if ( "since".equalsIgnoreCase(name)){
code.setCode("2012");
}
return code;
}
}
I want to create a Soap header structure like following :
<soapenv:Header>
<wataniya:auth xmlns:wataniya="http://osb.wataniya.com">
<username> TestUser</username>
<password> TestPassword </password>
</wataniya:auth>
</soapenv:Header>
I have written a code :
QName qName = new QName("http://osb.wataniya.com", "auth", "watania");
Element authElement = doc.getDocumentElement();
Element usernameElement = doc.createElement("username");
usernameElement.setTextContent("TestUser");
Element passwordElement = doc.createElement("password");
passwordElement.setTextContent("TestPassword");
authElement.appendChild(usernameElement);
authElement.appendChild(passwordElement);
Header header = new Header(qName, authElement);
I have used following imports(for reference):
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.camel.CamelExecutionException;
import org.apache.cxf.binding.soap.SoapFault;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.MessageContentsList;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
But I am facing issue and unable to generate the header as expected.
Any leads..thanks in advance
This is part of that question.
I want to integrate one system and the system strong required input/output params. The system works by wsdl. That's why I created a web-service on java :
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import java.util.Date;
#SOAPBinding(style=SOAPBinding.Style.DOCUMENT)
public class WebServices {
#WebMethod
public PerformTransactionResult Test2(){
PerformTransactionResult performTransactionResult = new PerformTransactionResult();
performTransactionResult.setErrorMsg("test");
return performTransactionResult;
}
}
my PerformTransactionResult class is:
import org.apache.cxf.aegis.type.java5.XmlType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "PerformTransactionResult")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "PerformTransactionResult")
public class PerformTransactionResult {
private String errorMsg;
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}
System, which I'm integrating want to get response like that:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<uws:PerformTransactionResult xmlns:uws="http://uws.provider.com/">
<errorMsg>Ok</errorMsg>
</uws:PerformTransactionResult>
</s:Body>
</s:Envelope>
My web-service is getting response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:Test2Response xmlns:ns1="http://wservices.myhost.lan/">
<return xmlns:ns2="http://wservices.myhost.lan/">
<errorMsg>test</errorMsg>
</return>
</ns1:Test2Response>
</soap:Body>
</soap:Envelope>
As you see, response should return PerformTransactionResult, not Test2Response. How to I implement that task ?
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