3

I am trying to change prefix for soap envelope in response of web-service from S="http://schemas.xmlsoap.org/soap/envelope/" to soap="http://schemas.xmlsoap.org/soap/envelope/":

so here's how the response looks like now:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <n:soaprequestResponse xmlns:n="http://tempuri.org/soaprequest">
         <n:soaprequestResult/>
      </n:soaprequestResponse>
   </S:Body>
</S:Envelope>

and here's how it must look like:

<soap:Envelope xmlns:soap:="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <n:soaprequestResponse xmlns:n="http://tempuri.org/soaprequest">
         <n:soaprequestResult/>
      </n:soaprequestResponse>
   </soap:Body>
</soap:Envelope>

How can this be attained?

EDIT:

I added soap handler class and the problem starts when I'm trying to get envelope:

package org.tempuri.soaprequest;

import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;


public class SoapHandler implements SOAPHandler<SOAPMessageContext> {

    @Override
    public Set<QName> getHeaders() {
       //do nothing
       return null;
    }

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        if ((boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) { //Check here that the message being intercepted is an outbound message from your service, otherwise ignore.
            try {
                SOAPEnvelope msg = context.getMessage().getSOAPPart().getEnvelope(); //just trying to get envelope
            } catch (SOAPException ex) {
                ex.printStackTrace();
            }

        return true; //indicates to the context to proceed with (normal)message processing
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
          //do nothing
       return true;
    }

    @Override
    public void close(MessageContext context) {
          //do nothing

    }
}

SoapUI throws:

<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
    <faultcode>S:Server</faultcode>
        <faultstring>JVMVRFY012 stack shapeinconsistent;class=com/sun/xml/messaging/saaj/soap/SOAPDocumentImpl, method=createDocumentFragment()Lorg/w3c/dom/DocumentFragment;, pc=5
    </faultstring>
</S:Fault>

Tomcat log has no errors.

It doesn't occur without custom soap handler.

Perhaps the reason is in the way I implemented web method. It creates a new thread with an object that processes request and then returns empty response, thus releasing client from waiting for request processing is over:

@WebResult(name="soaprequestResult", targetNamespace="http://tempuri.org/soaprequest")
public SoaprequestResponse.SoaprequestResult soaprequest(@WebParam(name="streams", targetNamespace="http://tempuri.org/soaprequest") SoaprequestStreams streams) {
    try {
        new Thread(new MyProcess(streams)).start();
        return new SoaprequestResponse().getSoaprequestResult();
    } catch(Exception e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        String stackTrace = sw.toString();
        return new SoaprequestResponse().getSoaprequestResult();
    }
}

and MyProcess is class where request processing really is and stmt.executeUpdate is executed.

griboedov
  • 876
  • 3
  • 16
  • 33
  • the `::` in `soap::Body` is an editing mistake, right ? – bvdb Jun 03 '15 at 14:49
  • Maybe a silly question, but why? Both are identical. Nevertheless: http://stackoverflow.com/questions/12889943/customising-jax-ws-prefix-of-a-soap-response – bvdb Jun 03 '15 at 14:53
  • @bvdb thanks for the link, but it explains changing body contents ns prefix – griboedov Jun 03 '15 at 14:54

1 Answers1

3

I think Customising JAX-WS prefix of a SOAP response summarizes your options.

Option 1: I think you just need to put this above your package.

@javax.xml.bind.annotation.XmlSchema(namespace = "http://schemas.xmlsoap.org/soap/envelope/",
   xmlns = { 
      @javax.xml.bind.annotation.XmlNs(prefix = "soap", 
         namespaceURI="http://schemas.xmlsoap.org/soap/envelope/")
    }
)

Option 2: Alternatively (also mentioned in the link), you could use a SOAPHandler. You could add a configuration file to bind these handlers. But in fact, you can just add them at runtime. I think this needs some explanation: The trick is to get an instance of the BindingProvider. This is different if you are a consumer or provider of the webservice.

If you are server (i.e. providing a webservice):

webservice = Class.forName(serviceClassName).newInstance();
Endpoint e = Endpoint.create(webservice);
BindingProvider bp = (BindingProvider)e.getBinding();
e.publish("http://localhost:" + serverPort + servicePath);

If you are client (i.e. consuming a webservice):

Service service = new Service(url, qname);
Port port = service.getPort();
BindingProvider bp = ((BindingProvider) port);

When you have the bindingprovider, you can bind the handler as follows.

List<Handler> chain = bp.getHandlerChain();
if (chain == null) chain = new ArrayList<Handler>();
chain.add(myCustomHandler);
bp.setHandlerChain(chain);

Now, for the chained handler itself, you should implement SOAPHandler<SOAPMessageContext>. There you can manipulate your messages however you like. (see linked post above for an example).

Community
  • 1
  • 1
bvdb
  • 22,839
  • 10
  • 110
  • 123
  • Is this applicable to web-service deployed at tomcat 8? – griboedov Jun 03 '15 at 16:12
  • 1
    Yes, this is just universal java webservice functionality. Should be applicable for all web containers. Note that all mentioned classes are in javax.ws package. – bvdb Jun 03 '15 at 17:07
  • @griboedov So, only option 2 worked ? (then I'll remove option 1) – bvdb Jun 03 '15 at 18:45
  • I tried solution explained in your link at the top, I added soap handler class and added handler-chain.xml, and now I'm getting: "JVMVRFY012 stack shape inconsistent; class=com/sun/xml/messaging/saaj/soap/SOAPDocumentImpl, method=createDocumentFragment()Lorg/w3c/dom/DocumentFragment;, pc=5" in soap response. So I'm trying to fix it. – griboedov Jun 04 '15 at 07:43
  • Worked for me, but anyone know if this will support renaming multiple namespaces? Such as the default "S" to "soap" in the SOAP Envelope, and, the XML response payload's message-specific "ns2" to something more meaningful like "myUniqueServiceName". – bcmoney Dec 11 '17 at 10:33
  • @bcmoney At least one of these 2 options should be able to help you, possibly both. Option1 uses an array, which allows you to define multiple namespaces (e.g. `xmlns={@XmlNs{...}, @XmlNs{...}}`). And option2 really does give you full control to create any output you like. (However, please note that nobody really confirmed that option1 worked even with 1 namespace.) – bvdb Dec 13 '17 at 18:01
  • 2
    @bvdb I can confirm it definitely worked! and with two... Here's a sample project I was playing with: – bcmoney Dec 15 '17 at 02:41