How to add soap header when making a soap request using the java objects generated by wsdl

╄→尐↘猪︶ㄣ 提交于 2019-11-28 22:04:19

Once I had the same problem. I needed to modify the JAX-WS web service SOAP header at every request. To solve this problem I have created a handler like this:

public class MyHandler implements SOAPHandler<SOAPMessageContext> {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyHandler.class);

    private String username;

    private String password;

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        try {
            SOAPMessage message = context.getMessage();
            SOAPHeader header = message.getSOAPHeader();
            SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
            if (header == null) {
                header = envelope.addHeader();
            }
            QName qNameUserCredentials = new QName("https://your.target.namespace/", "UserCredentials");
            SOAPHeaderElement userCredentials = header.addHeaderElement(qNameUserCredentials);

            QName qNameUsername = new QName("https://your.target.namespace/", "Username");
            SOAPHeaderElement username = header.addHeaderElement(qNameUsername );
            username.addTextNode(this.username);
            QName qNamePassword = new QName("https://your.target.namespace/", "Password");
            SOAPHeaderElement password = header.addHeaderElement(qNamePassword);
            password.addTextNode(this.password);

            userCredentials.addChildElement(username);
            userCredentials.addChildElement(password);

            message.saveChanges();
            //TODO: remove this writer when the testing is finished
            StringWriter writer = new StringWriter();
            message.writeTo(new StringOutputStream(writer));
            LOGGER.debug("SOAP message: \n" + writer.toString());
        } catch (SOAPException e) {
            LOGGER.error("Error occurred while adding credentials to SOAP header.", e);
        } catch (IOException e) {
            LOGGER.error("Error occurred while writing message to output stream.", e);
        }
        return true;
    }

    //TODO: remove this class after testing is finished
    private static class StringOutputStream extends OutputStream {

        private StringWriter writer;

        public StringOutputStream(StringWriter writer) {
            this.writer = writer;
        }

        @Override
        public void write(int b) throws IOException {
            writer.write(b);
        }
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        LOGGER.debug("handleFault has been invoked.");
        return true;
    }

    @Override
    public void close(MessageContext context) {
        LOGGER.debug("close has been invoked.");
    }

    @Override
    public Set<QName> getHeaders() {
        LOGGER.debug("getHeaders has been invoked.");
        return null;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

It adds the needed parameters to my SOAP header and it is invoked on every request. All you need to do is to modify handleMessage method to suit your needs.

Santosh

It works for me by overriding the public void setAttribute(String namespace, String localName, String value) method.

import javax.xml.namespace.QName;
import org.apache.axis.Constants;
import org.apache.axis.message.SOAPHeaderElement;

@SuppressWarnings("serial")
public class ADESHeaderElement  extends SOAPHeaderElement 
{

     public ADESHeaderElement(QName qname, Object value)
        {
            super(qname, value);
        }

     @Override
     public void setAttribute(String namespace, String localName, String value) 
     {
       if (!Constants.ATTR_MUST_UNDERSTAND.equals(localName)) 
       {  // Or any other attribute name you'd want to avoid
         super.setAttribute(namespace, localName, value);
       }
     }
}

Create header element like this:

 ADESHeaderElement custheader = new ADESHeaderElement(qname, clientserv);          
        custheader.setActor(null);

When you create your service from classess generated by cxf, add custom interceptor

Service service = new MyService(wsdlURL, new QName("http://myservice.com/MyService/", "MyService"));
MyPort port = service.getMyPort();
Client client = ClientProxy.getClient(port);
// adding interceptor programmatically
client.getOutInterceptors().add(new MyHeaderHandler());

Your can extend AbstractSoapInterceptor to implement your custom interceptor to handle message.

import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;

import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.apache.cxf.phase.Phase;

import com.rpc.core.utils.DomainContext;

public class MyHeaderHandler extends AbstractSoapInterceptor {

    /**
    * Constructor
    */
    public MyHeaderHandler() {
        super(Phase.PRE_LOGICAL);

    }

    @Override
    public void handleMessage(org.apache.cxf.binding.soap.SoapMessage message) throws org.apache.cxf.interceptor.Fault {
        try {
            message.getHeaders().add(new Header(new QName("MyCustomHeader"),"value", new JAXBDataBinding(String.class)));
             } catch (JAXBException e) {
                 e.printStackTrace();
             }
         };
     }
}
Oscarfm

Yes, I did the same that Rangappa Tungal, following this example:

Service w = new ServiceLocator();  
ServiceSoap ws = new ServiceSoapStub(new URL(w.getServiceSoapAddress()),w); Stub mystub = (Stub) ws;
AuthHeader up = new AuthHeader("user","pass");
mystub.setHeader("namespace", "AuthHeader", up);
ws.get***();

Link to the example!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!