Implement the SOAP Handler

In order to add the WS-Security SOAP header we need to implement a SOAPHandler<SOAPMessageContext> to inject the WS-Security header into every SOAP request made by the client.

A simple implementation of such a handler would look like:

package com.oracle.example;

import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.util.Set;

public class WSSEHandler implements SOAPHandler <SOAPMessageContext> {
    private static String WSSE_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    private static String PASSWORD_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
    private static String NAMESPACE_PREFIX = "wss";

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

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        //only handle outbound requests
        boolean isRequest = (boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if(isRequest){
            try {

                SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
                SOAPHeader header = envelope.getHeader();

                SOAPElement security = header.addChildElement("Security", NAMESPACE_PREFIX, WSSE_NAMESPACE);
                SOAPElement token = security.addChildElement("UsernameToken", NAMESPACE_PREFIX, WSSE_NAMESPACE);

                SOAPElement username = token.addChildElement("Username", NAMESPACE_PREFIX, WSSE_NAMESPACE);
                username.addTextNode("myusername"); //replace with actual username

                SOAPElement password = token.addChildElement("Password", NAMESPACE_PREFIX, WSSE_NAMESPACE);
                token.addChildElement(password);
                password.setAttribute("Type", PASSWORD_TYPE);
                password.addTextNode("..."); //replace with actual password

            } catch (SOAPException ex) {
                throw new RuntimeException("Error adding WS-Security Token: " + ex.getMessage(), ex);
            }
        }

        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return false;
    }

    @Override
    public void close(MessageContext context) {

    }
}