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

Venu Doddi picture Venu Doddi · Aug 14, 2012 · Viewed 73.8k times · Source

I generated client java objects using JAX-WS RI. I am trying to make a SOAP request to a web service. Service requires authentication in the header which looks like below:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<xsd:authHeader>
<xsd:user>[email protected]</xsd:user>
<xsd:password>password1</xsd:password>
</xsd:authHeader>
</soapenv:Header>
<soapenv:Body>
<ns:searchAssetsParam>
<ns:includeSubfolders>true</ns:includeSubfolders>
<ns:resultsPage>2</ns:resultsPage>
</ns:searchAssetsParam>
</soapenv:Body>
</soapenv:Envelope>

The generated java objects have methods for calling the service, creating the objects and constructing the header. But, I am having trouble setting the header while making the call.

Here's the code that I am using:

IpsApiService service = new IpsApiService();
IpsApiPortType port = service.getIpsApiSoapPort();
SearchAssetsParam searchAssetsParam = buildSearchAssetsParam();
SearchAssetsReturn response = port.searchAssets(searchAssetsParam);

buildSearchAssetsParam() constructs the request object. I created the header object as follows:

AuthHeader header = new AuthHeader();
header.setUser("[email protected]");
header.setPassword("password1");

How do I set this AuthHeader to the service request?

Thanks, Venu

Answer

Paulius Matulionis picture Paulius Matulionis · Oct 3, 2012

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.