Java (web service - SOAP) - How do I add a SOAP handler on the client side and enable MTOM correct?
Asked Answered
R

1

5

Java - JDK 1.6.0.7 - WSGEN -version: JAX-WS RI 2.2.3-b01-


I have the following problem:

SOAPBinding binding = (SOAPBinding)((BindingProvider)port).getBinding();
binding.setMTOMEnabled(true);

List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.addAll(binding.getHandlerChain());
handlerChain.add(new MyHandlerSecurity("admin", "admin"));
binding.setHandlerChain(handlerChain);

With this code the SoapHeader is correct, but the attachment is always a inline base64 text.

//List<Handler> handlerChain = new ArrayList<Handler>();
//handlerChain.addAll(binding.getHandlerChain());
//handlerChain.add(new MyHandlerSecurity("admin", "admin"));
//binding.setHandlerChain(handlerChain);

When handlerChain is commented out, you will see the attachment as an xop reference, but there is no SoapHeader and thus, the client is not authenticated...

How can I add a handler on the client side and enable MTOM correct?

Rancidity answered 17/9, 2012 at 13:7 Comment(0)
C
8

Im not sure if i got the question right, but i think i had your same problem a couple of months ago, so here is my solution:

First you need a HeaderHandler class , wich creates the soap header element, it should look like this:


    import javax.xml.namespace.QName;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPEnvelope;
    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;


    public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {

        public boolean handleMessage(SOAPMessageContext smc) {
            Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            String AUTH_TK = "http://www.myurl.com:port/subdir/etc/";
            String NOPREFIX="";//no prefix
            String PREFIX_XMLNS="xmlns";
            String value =  "123456";
            if (outboundProperty.booleanValue()) {
                try {
                    SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
                    SOAPHeader header = envelope.addHeader();
                    //<AuthorizationToken xmlns="http://www.myurl.com:port/subdir/etc/">
                    SOAPElement authorizationToken = header.addChildElement("AuthorizationToken", PREFIX_XMLNS, AUTH_TK);
                    //<Token>value</Token>
                    SOAPElement usernameToken =
                        authorizationToken.addChildElement("Token", NOPREFIX);
                        usernameToken.addTextNode(value);
                        //<Token>value</Token>
                    SOAPElement usernameToken =
                        authorizationToken.addChildElement("Token", PREFIX);
                        usernameToken.addTextNode(value);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return outboundProperty;
        }


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

        public void close(MessageContext arg0) {

        }

        public boolean handleFault(SOAPMessageContext arg0) {
            return false;
        }
    }

After that you create a HeaderHandlerResolver to handle the header creation and insert it in a handler chain:


    import java.util.ArrayList;
    import java.util.List;
    import javax.xml.ws.handler.Handler;
    import javax.xml.ws.handler.HandlerResolver;
    import javax.xml.ws.handler.PortInfo;

    public class HeaderHandlerResolver implements HandlerResolver {

    @SuppressWarnings("unchecked")
    public List<Handler> getHandlerChain(PortInfo portInfo) {
          List<Handler> handlerChain = new ArrayList<Handler>();
          HeaderHandler hh = new HeaderHandler();
          handlerChain.add(hh);
          return handlerChain;
       }
    }

After that, you add in the Client:


        try{
            //new service instance (your service should be extending javax.xml.ws.Service;)
            YourServiceProxy service = new YourServiceProxy();
            //calls the header handler resolver ;)
            service.setHandlerResolver(new HeaderHandlerResolver());
            //get the service
            YourService port = (YourService)service.getYourService();
            //call the service 
            port.yourMethod()   
        } catch (Exception e) {
            e.printStackTrace();
        }

By the way, i didn't tested this particular header, i modified a previous header handler i had, so it may be not accurate, but i think it's pretty close, i really hope it helps you, try it out and tell us how it comes, i'll try to help you if it still doesn't works.

Chinaman answered 17/9, 2012 at 13:7 Comment(3)
This answer was usefult for me when I needed to set up a loggingHandler (something which logs out the requests / responses) in a ws client. Thanks.Krever
What is the result of returning false from the handleFault method? And what about returning null from the getHeaders method?Gateshead
@NicholasDiPiazza returning false will block the message processing, you are basically saying "if this handler fails discard the entire message" check docs.oracle.com/javaee/5/api/javax/xml/ws/handler/… When returning null in getHeaders you are "this handler handles no specific header", which is why we then have our own handler resolver, retrospectively you can probably get rid of the handler resolver by returning the right headers but I haven't tried it docs.oracle.com/javaee/5/api/javax/xml/ws/handler/soap/…Chinaman

© 2022 - 2024 — McMap. All rights reserved.