how to add namespace in soap web service response - java

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;
}
}

Related

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

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>

Return an object on wsdl response

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 ?

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.

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

WebService with Apache CXF and custom headers

I created a web service using Apache cfx and spring, it works, but I need that the response include this header
<?xml version="1.0" encoding="UTF-8"?>
Right now the response is like this.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:postEncuestaResponse xmlns:ns2="http://webservice.atomsfat.com/">
<respuestaEncuesta>
<dn>12315643154</dn>
<encuestaPosted>true</encuestaPosted>
<fecha>2009-09-30T16:32:33.163-05:00</fecha>
</respuestaEncuesta>
</ns2:postEncuestaResponse>
</soap:Body>
</soap:Envelope>
But should be like this
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:postEncuestaResponse xmlns:ns2="http://webservice.atomsfat.com/">
<respuestaEncuesta>
<dn>12315643154</dn>
<encuestaPosted>true</encuestaPosted>
<fecha>2009-09-30T16:32:33.163-05:00</fecha>
</respuestaEncuesta>
</ns2:postEncuestaResponse>
</soap:Body>
</soap:Envelope>
This is the configuration of the beans of spring that expose the service.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="encuestas"
implementor="webservice.serviceImpl"
address="/Encuestas" >
</jaxws:endpoint>
</beans>
this is the interface
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
#WebService
public interface Encuestas {
#WebResult(name= "respuestaEncuesta")
RespuestaEncuestaMsg postEncuesta (#WebParam(name = "encuestaMsg") EncuestaMsg message);
}
Any ideas ?
Or use CXF build-in configuration capabilities.
Just add this IN your CXF Spring config :
<jaxws:properties>
<entry key="org.apache.cxf.stax.force-start-document">
<bean class="java.lang.Boolean">
<constructor-arg value="true"/>
</bean>
</entry>
</jaxws:properties>
Check the following
How can I add soap headers to the request/response?
Adding JAX-WS handlers to web services
Converting JAX-WS handlers to Apache CXF interceptors
then decide for one of the options and implement a handler/interceptor which adds what you need.
Well I implement a Handler, first I downloaded the examples from CXF and modified the logging Handler, and it works.
The configuration of spring :
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="encuestas"
implementor="com.webservice.EncuestasImpl"
address="/Encuestas">
<jaxws:handlers>
<bean class="com.webservice.HeaderHandler"/>
</jaxws:handlers>
</jaxws:endpoint>
And the code this is the code for the handler.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.webservice;
import java.io.PrintStream;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/*
* This simple logical Handler will output the payload of incoming
* and outgoing messages.
*/
public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {
private PrintStream out;
public HeaderHandler() {
setLogStream(System.out);
}
protected final void setLogStream(PrintStream ps) {
out = ps;
}
public void init(Map c) {
System.out.println("LoggingHandler : init() Called....");
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleMessage(SOAPMessageContext smc) {
System.out.println("LoggingHandler : handleMessage Called....");
logToSystemOut(smc);
return true;
}
public boolean handleFault(SOAPMessageContext smc) {
System.out.println("LoggingHandler : handleFault Called....");
logToSystemOut(smc);
return true;
}
// nothing to clean up
public void close(MessageContext messageContext) {
System.out.println("LoggingHandler : close() Called....");
}
// nothing to clean up
public void destroy() {
System.out.println("LoggingHandler : destroy() Called....");
}
/*
* Check the MESSAGE_OUTBOUND_PROPERTY in the context
* to see if this is an outgoing or incoming message.
* Write a brief message to the print stream and
* output the message. The writeTo() method can throw
* SOAPException or IOException
*/
protected void logToSystemOut(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean)
smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
out.println("\nOutbound message:");
} else {
out.println("\nInbound message:");
}
SOAPMessage message = smc.getMessage();
try {
message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
message.writeTo(out);
out.println();
} catch (Exception e) {
out.println("Exception in handler: " + e);
}
}
}
Note: that in the try I use MessageContext.MESSAGE_OUTBOUND_PROPERTY like Justin suggested.
Folowing the links provided by jitter, I went to http://cxf.apache.org/faq.html#FAQ-HowcanIaddsoapheaderstotherequest%252Fresponse%253F and found the following solution:
// My object of the custom header
AuthenticationHeader aut = new AuthenticationHeader();
aut.setUserName("ws");
aut.setPassword("ws123");
IntegrationWS integration = new IntegrationWS();
List<Header> headers = new ArrayList<Header>();
Header dummyHeader;
try {
dummyHeader = new Header(new QName("http://www.company.com/ws/", "AuthenticationHeader"), auth, new JAXBDataBinding(AuthenticationHeader.class));
} catch (JAXBException e) {
throw new IllegalStateException(e);
}
headers.add(dummyHeader);
IntegrationWSSoap soapPort = integration.getIntegrationWSSoap12();
//client side:
((BindingProvider)soapPort).getRequestContext().put(Header.HEADER_LIST, headers);
ArrayOfBrand arrayBrand = soapPort.syncBrands();
I don't have Apache CXF specific knowledge, but the jax-ws way to add the xml declaration seems to be to make a handler and use SOAPMessage.setProperty() to turn that feature on:
message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
You should be able to add a jax-ws handler to your endpoint by adding a jaxws:handlers element in that spring config.

Categories

Resources