How to enable WS-Addresing in client SOAP request for Grails - java

I have a problem with WS-Addresing in SOAP header. I succesfully imported classes from xsd file with configuration, but server require WS-Addressing attributes in soap header("wsa:action", "wsa:to"). Unfortunettly client service dont inject these attributes and server return http code 400 "Bad Request".
How can I automatically inject a proper SOAP header for requests?
I tried with #Addressing(enabled=true, required=true) annotation, but header was wrong for webservice
Configuration in Config.groovy
Service endpoint: https://wyszukiwarkaregontest.stat.gov.pl/wsBIR/UslugaBIRzewnPubl.svc
Main xsd file: https://wyszukiwarkaregontest.stat.gov.pl/wsBIR/wsdl/UslugaBIRzewnPubl.xsd
I use Grails 2.5.0 and plugin grails-cfx
Grails-cfx configuration in Config.groovy
birCompanyDataEndPoint {
wsdl = "wsdl/UslugaBIRzewnPubl.xsd"
namespace = "pl.truesoftware.crm.company.regon"
client = true
contentType = "application/soap+xml"
mtomEnabled = true
exsh = true
or = true
wsdlArgs = ['-autoNameResolution']
// outInterceptors = 'smartApiMetaOutInterceptor'
clientInterface = IUslugaBIRzewnPubl
serviceEndpointAddress = "https://wyszukiwarkaregontest.stat.gov.pl/wsBIR/UslugaBIRzewnPubl.svc"
}
Example
Plain SOAP request from client service
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DaneKomunikat xmlns="http://CIS/BIR/PUBL/2014/07/DataContract" xmlns:ns2="http://CIS/BIR/PUBL/2014/07" xmlns:ns3="http://CIS/BIR/2014/07" xmlns:ns4="http://schemas.microsoft.com/2003/10/Serialization/"/>
</soap:Body>
</soap:Envelope>
With using annotation #Addressing(enabled=true, required=true)
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Action xmlns="http://www.w3.org/2005/08/addressing">http://CIS/BIR/PUBL/2014/07/IUslugaBIRzewnPubl/DaneKomunikat</Action>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:f43e7c86-99dd-42fc-a626-ccbd44136682</MessageID>
<To xmlns="http://www.w3.org/2005/08/addressing">https://wyszukiwarkaregontest.stat.gov.pl/wsBIR/UslugaBIRzewnPubl.svc</To>
<ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
</ReplyTo>
</soap:Header>
<soap:Body>
<ns2:DaneKomunikat xmlns="http://CIS/BIR/PUBL/2014/07/DataContract" xmlns:ns2="http://CIS/BIR/PUBL/2014/07" xmlns:ns3="http://CIS/BIR/2014/07" xmlns:ns4="http://schemas.microsoft.com/2003/10/Serialization/"/>
</soap:Body>
</soap:Envelope>
Expected
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="http://CIS/BIR/PUBL/2014/07">
<soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:To>https://wyszukiwarkaregontest.stat.gov.pl/wsBIR/UslugaBIRzewnPubl.svc</wsa:To>
<wsa:Action>http://CIS/BIR/PUBL/2014/07/IUslugaBIRzewnPubl/DaneKomunikat</wsa:Action>
</soap:Header>
<soap:Body>
<ns:DaneKomunikat/>
</soap:Body>
</soap:Envelope>
Update with solution
Created two cfx interceptor. First convert soap addressing tags(Action, To) to acceptable format
public class BirSoapHeaderInterceptor extends AbstractSoapInterceptor
{
static String birSID = ""
public BirSoapHeaderInterceptor() {
super(Phase.PRE_PROTOCOL);
}
#Override
public void handleMessage(SoapMessage message) throws Fault
{
try
{
message.put("disable.outputstream.optimization", true)
List<Header> soapHeaders = message.getHeaders()
//----------------- copy values from old header
String wsaAction = ""
String wsaTo = ""
soapHeaders.each { tag ->
log.debug("Soap request header tag: ${tag.name} ${tag.dataBinding}")
String tagName = (tag.name as String)
def objectValue = tag.object?.value
if (!wsaAction && tagName.contains("Action"))
wsaAction = objectValue?.value
if (!wsaTo && tagName.contains("To"))
wsaTo = objectValue?.value
}
soapHeaders.clear()
//-----------------wsa:To
Header headTo = new Header(new QName("http://www.w3.org/2005/08/addressing", "To", "wsa"), wsaTo, new JAXBDataBinding(String.class))
soapHeaders.add(headTo)
//-----------------wsa:Action
Header headAction = new Header(new QName("http://www.w3.org/2005/08/addressing", "Action", "wsa"), wsaAction, new JAXBDataBinding(String.class))
soapHeaders.add(headAction)
message.put(Header.HEADER_LIST, soapHeaders)
//Session identyficator in HTTP Header
if(birSID.length())
{
Map<String, List<String>> outHeaders = (Map<String, List<String>>) message.get(Message.PROTOCOL_HEADERS)
outHeaders.put("sid", Arrays.asList(birSID));
message.put(Message.PROTOCOL_HEADERS, outHeaders);
}
} catch (SOAPException e)
{
log.error(e)
}
}
}
Second interceptor converts attributes 'xmlns:soap', 'xmlns:wsa', 'xmlns:soap' with acceptable namespaces
class BirSoapContextInterceptor implements SOAPHandler<SOAPMessageContext>
{
/*
Based on https://stackoverflow.com/questions/10678723/changing-jax-ws-default-xml-namespace-prefix
*/
public boolean handleMessage(final SOAPMessageContext context)
{
try
{
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope envelope = soapMsg.getSOAPPart().getEnvelope()
soapMsg.getSOAPPart().getEnvelope().removeAttributeNS("http://schemas.xmlsoap.org/soap/envelope/", "soap");
soapMsg.getSOAPPart().getEnvelope().removeAttributeNS("http://www.w3.org/2000/xmlns/", "soap");
soapMsg.getSOAPPart().getEnvelope().removeAttribute("xmlns:soap");
soapMsg.getSOAPPart().getEnvelope().removeNamespaceDeclaration("xmlns:soap")
envelope.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:soap", "http://www.w3.org/2003/05/soap-envelope");
envelope.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:ns", "http://CIS/BIR/PUBL/2014/07");
soapMsg.getSOAPHeader().setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:wsa", "http://www.w3.org/2005/08/addressing")
soapMsg.getSOAPHeader().setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:soap", "http://www.w3.org/2003/05/soap-envelope");
soapMsg.saveChanges()
context.setMessage(soapMsg)
} catch (SOAPException e)
{
e.printStackTrace();
}
return true;
}
#Override
boolean handleFault(SOAPMessageContext context) {
return false
}
#Override
void close(MessageContext context) {
log.debug("Closing...")
}
#Override
Set<QName> getHeaders() {
return null
}
}

Related

How to retrieve From/Address value in SOAP header (in Java/SpringBoot)

I'm trying to create a Spring Boot SOAP application using this tutorial: https://www.baeldung.com/spring-boot-soap-web-service Everything works like a charm so far.
Task: I'd like to access the SOAP header.
This is what I've done so far:
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
#ResponsePayload
public GetCountryResponse getCountry(#RequestPayload GetCountryRequest request) {
[..]
}
I can just extend this with MessageContext:
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
#ResponsePayload
public GetCountryResponse getCountry(#RequestPayload GetCountryRequest request, MessageContext messageContext) {
[..]
}
This MessageContext plus a little util method fooBar is supposed to access the SOAP header:
protected static String fooBar(final MessageContext messageContext) {
SoapHeader soapHeader = ((SoapMessage) messageContext.getRequest()).getSoapHeader();
[...]
}
So far so good. This is what my SOAP message looks like:
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
[...]
xmlns:wsa="http://www.w3.org/2005/08/addressing">
<soap:Header>
[...]
<wsa:From>
<wsa:Address>http://from-endpoint</wsa:Address>
</wsa:From>
[...]
</soap:Header>
<soap:Body>
[...]
</soap:Body>
</soap:Envelope>
I would like to get the address in <From><Address>: http://from-endpoint .. but now it starts to get awkward..
protected static String fooBar(final MessageContext messageContext) {
SoapHeader soapHeader = ((SoapMessage) messageContext.getRequest()).getSoapHeader();
Iterator<SoapHeaderElement> soapHeaderElementIterator = soapHeader.examineAllHeaderElements();
while (soapHeaderElementIterator.hasNext()) {
SoapHeaderElement soapHeaderElement = soapHeaderElementIterator.next();
if (soapHeaderElement.getName().getLocalPart().equals("From")) {
[...]
This works as expected, but this SoapHeaderElement is type org.springframework.ws.soap.SoapHeaderElement which gives me no options to access further child elements.
What am I doing wrong here?
...
...
...
✅ SOLUTION has been found - see comments
Thanks to help of M. Deinum I've found a solution:
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
#ResponsePayload
public GetCountryResponse getCountry(#RequestPayload GetCountryRequest request, MessageContext messageContext) {
Addressing10 addressing10 = new Addressing10();
MessageAddressingProperties messageAddressingProperties = addressing10.getMessageAddressingProperties((SoapMessage) messageContext.getRequest());
URI address = messageAddressingProperties.getFrom().getAddress();
}

Soap Header is fetched as null using SOAPMessage.getSOAPHeader() while retrieving custom SOAP header

I am trying to extract custom SOAP header using the chain-handler mechanism as below:
Webservice:
`#HandlerChain(file="handler-chain.xml")
public class CustomAPI extends SessionBeanBase {
#WebMethod
public GetBalanceResponse getBalances(
#WebParam(name="subscriptionId")long subscriptionId,
#WebParam(name="validityPeriodFromDt")Date validityPeriodFromDt,
#WebParam(name="validityPeriodToDt")Date validityPeriodToDt) throws APIException
{
try {
GetBalancesItem item = new GetBalancesItem(subscriptionId, validityPeriodFromDt, validityPeriodToDt);
final BalanceBusinessLogic api = (BalanceBusinessLogic)startCall(RSLogic.class, this, "getBalances");
BusinessLogicCallable<GetBalancesItem> t = new BusinessLogicCallable<GetBalancesItem>() {
public Response callBusinessLogic(GetBalancesItem getBalancesItem) throws CCSException, APIException {
Date validityPeriodFromDt = getBalancesItem.getValidityPeriodFromDt();
Date validityPeriodToDt = getBalancesItem.getValidityPeriodToDt();
long subscriptionId = getBalancesItem.getSubscriptionId();
return api.checkBalance(subscriptionId, validityPeriodFromDt, validityPeriodToDt);
}
};
return (GetBalanceResponse)callBusinessLogic(t, item);
} catch (Throwable e) {
// Handle exception (and rethrow it hence the need for return null)
handleExceptions(e);
return null;
}
}`
Handler-chain. xml as:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/javaee_web_services_metadata_handler_2_0.xsd">
<handler-chain>
<handler>
<handler-name>ApiSoapHandler</handler-name>
<handler-class>com.api.framework.ApiSoapHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>
ApiSOAPhandlercode as:
public boolean handleMessage(SOAPMessageContext context) {
logger.debug("Inside ApiSoapHandler");
try {
SOAPMessage message = context.getMessage();
SOAPPart soapPart= message.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
if (soapEnvelope.getHeader() == null) {
soapEnvelope.addHeader();
}
// set the soap header
SOAPHeader latestSOAPHeader = soapHeader.get();
if (latestSOAPHeader != null) {
Iterator iterator = latestSOAPHeader.getChildElements();
while(iterator.hasNext()) {
SOAPHeaderElement soapHeaderElement = (SOAPHeaderElement)iterator.next();
soapEnvelope.getHeader().addChildElement(soapHeaderElement);
}
}
message.saveChanges();
System.out.println("header" + header.getAttribute("token"));
} catch (Exception e) {
logger.error("Error occurred while adding credentials to SOAP header.",
e);
}
return true;
}
The problem is that my header is fetched as null here . can anyone please suggest how to get the header here . For the reference , here is my sample SOAP request :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:bal="http://balance.api.ccs.cerillion.com/">
<soapenv:Header>
<token>187328364</token>
<soapenv:Header/>
<soapenv:Body>
<bal:getBalances>
<subscriptionId>664</subscriptionId>
</bal:getBalances>
</soapenv:Body>
</soapenv:Envelope>
While extracting token , am getting null in my code .

How can convert local xml file to org.ksoap2.serialization.SoapObject?

I am developing android web application which needs to connect web - service for response.
I am using kSOAP for web service invocation process.
[kSOAP is a SOAP web service client library for constrained Java environments such as Applets or J2ME applications.]
If I am saving that responded xml into the local directory, eg. /mnt/sdcard/appData/config.xml and then when ever I ask request for web service, first it will checks if local file is there then consider that file as responded file otherwise connect to the server.
This process reduce response time and increase efficiency of application.
Is it possible to convert it ('config.xml') to SOAP object? And How?
Consider my xml local file is as below:
config.xml
<?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>
<Response xmlns="http://testuser.com/webservices/response">
<Result>
<SName>Test User</SName>
<UnitDesc>SAMPLE Test </UnitDesc> <RefreshRate>60</RefreshRate>
<Out>
<Definition>
<Code>ABC</Code>
<Description>(Specific)</Description>
<Action>true</Action>
<Despatch>false</Despatch>
</Definition>
<Definition>
<Code>CDE</Code><Description>(Specific)</Description>
<ActionDate>true</ActionDate>
</Definition>
</Out>
<SampleText>
<string>Test XML Parsing</string>
<string>Check how to convert it to SOAP response</string>
<string>Try if you know</string>
</SampleText>
<GeneralData>
<Pair>
<Name>AllowRefresh</Name>
<Value>Y</Value>
</Pair>
<Pair>
<Name>ListOrder</Name>
<Value>ACCENDING</Value>
</Pair>
</GeneralData>
</Result>
</Response>
</soap:Body>
</soap:Envelope>
Current code is shown below:
final String CONFIGURATION_FILE="config.xml";
File demoDataFile = new File("/mnt/sdcard/appData");
boolean fileAvailable=false;
File[] dataFiles=demoDataFile.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String filename) {
return filename.endsWith(".xml");
}
});
for (File file : dataFiles) {
if(file.getName().equals(CONFIGURATION_FILE))
{
fileAvailable=true;
}
}
if(fileAvailable)
{
//**What to do?**
}
else
{
//Create the envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
//Put request object into the envelope
envelope.setOutputSoapObject(request);
//Set other properties
envelope.encodingStyle = SoapSerializationEnvelope.XSD;
envelope.dotNet = true;
String method="test";
synchronized (transportLockObject)
{
String soapAction = "http://testuser.com/webservices/response/"+method;
try {
transport.call(soapAction, envelope);
} catch (SSLHandshakeException she) {
she.printStackTrace();
SecurityService.initSSLSocketFactory(ctx);
transport.call(soapAction, envelope);
}
}
//Get the response
Object response = envelope.getResponse();
//Check if response is available... if yes parse the response
if (response != null)
{
if (sampleResponse != null)
{
sampleResponse.parse(response);
}
}
else
{
// Throw no response exception
throw new NoResponseException("No response received for " + method + " operation");
}
}
You can extend HttpTransportSE class and override method call like this:
public void call(String soapAction, SoapEnvelope envelope) throws IOException, XmlPullParserException
{
if(localFileAvailable)
{
InputStream is = new FileInputStream(fileWithXml);
parseResponse(envelope, is);
is.close();
}
else
{
super.call(soapAction, envelope);
}
}
The question was how to convert an xml file to a SoapObject. So how to get your input xml envelope into a ksoap2 call.
The way to do this is actually available within the HttpTransportSE class even though this was not its intended use!
There is a method "parseResponse" that takes in the envelope and an input stream(your xml file) and updates the envelope input header and body. But the clever thing is that you can copy these into the outHeader and outBody fields and then all the hard work of mapping fields goes away.
#Override
public void call(String soapAction, SoapEnvelope envelope) throws IOException, XmlPullParserException {
if ( getFileInputStream() != null ){
parseResponse(envelope, getFileInputStream());
envelope.bodyOut = envelope.bodyIn;
envelope.headerOut = envelope.headerIn;
getFileInputStream().close();
}
super.call(soapAction,envelope);
}

Java API not getting SOAPHeader from SOAP Request

I have developed a webservice in java using Metro RI( Along with an AuthenticationHandler), But when I am sending a SOAP request to the webservice, I am not able to get the SOAPHeader in the SOAPHandler.
Below is the SOAP Request which I am passing to the webservice.(I am using SOAP UI for this purpose)
`
<soapenv:Envelope xmlns:ser="http://server.webservice.bank/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-4" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>kshitij.jain</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">Phone0144</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">jf97anyZJUpR216tw4GRIw==</wsse:Nonce>
<wsu:Created>2013-05-15T17:38:49.610Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ser:getCreditCardTransaction>
<cardId>2</cardId>
<amt>109</amt>
<!--Optional:-->
<descr>test</descr>
</ser:getCreditCardTransaction>
</soapenv:Body>
</soapenv:Envelope>
`
Following is my code for webservice and Handler :
`
#WebService(serviceName = "getTransaction")
#HandlerChain(file = "ServerHandler.xml")
public class getTransaction {
#Inject
TransactionService tranService;
#Resource
private WebServiceContext wsContext;
#WebMethod(operationName = "getCreditCardTransaction")
public CreCardTranResponse getCreditCardTransaction(#WebParam(name = "cardId") int cardId, #WebParam(name = "amt") int amt, #WebParam(name = "descr") String descr) {
CreCardTranResponse res = new CreCardTranResponse();
tranService.addTransaction(amt, descr, "Debit", cardId);
res.setAmtDeducted(new Integer(amt).toString());
res.setCardID(new Integer(cardId).toString());
ReturnMessage ret = new ReturnMessage();
ret.setReturnCode("0");
ret.setReturnMessage("Successful");
res.setRetMessage(ret);
return res;
}
}
`
`
public class AuthenticationHandler implements SOAPHandler<SOAPMessageContext> {
private static Set<QName> headers;
static {
HashSet<QName> set = new HashSet<QName>();
set.add(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security"));
headers = Collections.unmodifiableSet(set);
}
#Override
public Set<QName> getHeaders() {
return headers;
}
#Override
public boolean handleMessage(SOAPMessageContext context) {
try {
handleSecurityMessage(context);
} catch (SOAPException ex) {
}
return true;
}
public boolean handleSecurityMessage(SOAPMessageContext context) throws SOAPException {
SOAPHeader soapHeader = context.getMessage().getSOAPHeader();
SOAPFault fault = SOAPFactory.newInstance().createFault();
if (soapHeader == null) {
fault.setFaultCode("failed");
fault.setFaultString("Soap header missing");
throw new SOAPFaultException(fault);
}
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
#Override
public void close(MessageContext context) {
}
}
`
Below is the serverHandler.xml
`
<?xml version="1.0" encoding="UTF-8"?>
<handler-config>
<handler-chain>
<handler-chain-name>AuthenticationHandlerChain</handler-chain-name>
<handler>
<handler-name>AuthenticationHandler</handler-name>
<handler-class>bank.webservice.security.AuthenticationHandler</handler-class>
</handler>
</handler-chain>
</handler-config>
`
I have already wasted 2 days on this, But After adding the header from SOAP UI also, code is showing header as null .
Is it the problem with SOAP UI or with the code?

Changing SOAPRequest Prefix in JAX-WS

How to change SOAP Request prefix in JAX-WS. I updated setprofix method in handlemessage
SOAPMessage msgs = ctx.getMessage();
SOAPMessage sm = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage();
sm.getSOAPPart().getEnvelope().setPrefix("soap");
sm.getSOAPPart().getEnvelope().removeNamespaceDeclaration("env");
sm.getSOAPHeader().setPrefix("soap");
sm.getSOAPBody().setPrefix("soap");*/
But Still I am getting the Same Request
<?xml version="1.0"?>
<S:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
I needed
<Soap:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Please help
final SOAPMessage soapMsg = context.getMessage();
soapMsg.getSOAPPart().getEnvelope().setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
soapMsg.getSOAPPart().getEnvelope().removeAttributeNS("http://schemas.xmlsoap.org/soap/envelope/", "env");
soapMsg.getSOAPPart().getEnvelope().removeAttribute("xmlns:env");
soapMsg.getSOAPPart().getEnvelope().setPrefix("soap");
soapMsg.getSOAPBody().setPrefix("soap");
soapMsg.getSOAPPart().getEnvelope().getHeader().detachNode();
I need to change the default prefix from S to soapenv. Here is what I did:
Create an implementation of SOAPHandler, which sets the prefix.
public class SoapNamespaceHandler implements SOAPHandler<SOAPMessageContext>{
private final static String SOAP_PREFIX = "soapenv";
#Override
public boolean handleMessage(final SOAPMessageContext context){
//only update the namespace prefix for outbound messages (requests)
final Boolean isSoapRequest = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (isSoapRequest){
try{
//get the soap message and envelope
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope env = soapMsg.getSOAPPart().getEnvelope();
//set the prefix
env.setPrefix(SOAP_PREFIX);
// **** apply the changes to the message
soapMsg.saveChanges();
}
catch (SOAPException e) {
e.printStackTrace();
}
}
return true;
}
Do one of the following:
create an XML file that functions as a HandlerResolver (see Changing JAX-WS default XML namespace prefix) and then annotate your web service client class with #HandlerChain(file = "handler.xml")
<?xml version="1.0" encoding="UTF-8"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
<handler-chain>
<handler>
<handler-name>mypackage.SoapNamespaceHandler</handler-name>
<handler-class>mypackage.SoapNamespaceHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>
create an implementation of HandlerResolver ...
public class SoapNamespaceHandlerResolver implements HandlerResolver {
#SuppressWarnings({ "rawtypes" })
#Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
Handler handler = (SOAPHandler<SOAPMessageContext>) new SoapNamespaceHandler();
String bindingID = portInfo.getBindingID();
if (bindingID.equals("http://schemas.xmlsoap.org/wsdl/soap/http")) {
handlerChain.add(handler);
} else if (bindingID.equals("http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")) {
handlerChain.add(handler);
}
return handlerChain;
}
}
... and then programmatically attach your HandlerResolver implementation to your web service client by calling
webServiceClient.setHandlerResolver(new SoapNamespaceHandlerResolver());

Categories

Resources