java web service client, adding http headers

后端 未结 5 1431
闹比i
闹比i 2020-12-14 02:43

Having created a java web service client using wsimport on a wsdl, I need to set the Authorization header for each soap message embedded in an http request. Having generated

5条回答
  •  抹茶落季
    2020-12-14 03:40

    For the sake of completeness and to help others in similar situations, I'd like to illustrate the IMHO cleanest solution using the JAX-WS-handler-chain:

    1) Sub-class your service-class (not the port-class) in a different (non-generated) package. Because the service-class (and its entire package) was likely generated from a WSDL, your changes to the sub-class are not lost, when you update your service-class after a WSDL change.

    2) Annotate your service-sub-class like this (import javax.jws.HandlerChain):

    @HandlerChain(file="HandlerChain.xml")
    public class MyService extends GeneratedService {
    

    3) Create a file called HandlerChain.xml in the same package as your service-sub-class, i.e. next to MyService with the following content:

    
    
        
            
                co.codewizards.example.HttpHeaderExtensionSOAPHandler
                co.codewizards.example.HttpHeaderExtensionSOAPHandler
            
        
    
    

    You may add multiple elements, btw.

    And make sure that this file really ends up in your JAR! For example, when using Maven, you have to place it either in ${project}/src/main/resources/ (instead of ${project}/src/main/java/) or you have to change your build-configuration to include resources from the java-folder! I recommend the latter, because it's cumbersome to have a parallel package-structure in the resources-folder, which is often forgotten during refactorings.

    4) Implement your HttpHeaderExtensionSOAPHandler -- similar to this:

    import static com.google.common.base.Preconditions.*;
    
    import java.util.*;
    
    import javax.xml.namespace.QName;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.soap.SOAPHandler;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    
    import co.codewizards.webservice.WebserviceContext;
    
    public class HttpHeaderExtensionSOAPHandler implements SOAPHandler {
    
        @Override
        public boolean handleMessage(SOAPMessageContext context) {
            checkNotNull(context, "context");
    
            Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            checkNotNull(outboundProperty, "outboundProperty");
    
            if (outboundProperty.booleanValue()) {
                WebserviceContext webserviceContext = WebserviceContext.getThreadWebserviceContextOrFail();
                String something = (String) webserviceContext.___(); // my API method ;-)
    
                @SuppressWarnings("unchecked")
                Map> requestHeaders = (Map>) context.get(MessageContext.HTTP_REQUEST_HEADERS);
                if (requestHeaders == null) {
                    requestHeaders = new HashMap>();
                    context.put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);
                }
                requestHeaders.put(MyService.MY_CONSTANT, Collections.singletonList(something));
            }
            return true;
        }
    
        @Override
        public boolean handleFault(SOAPMessageContext context) { return true; }
    
        @Override
        public void close(MessageContext context) { }
    
        @Override
        public Set getHeaders() { return Collections.emptySet(); }
    }
    

    In my example above (and in my productive code) I obtain the data to be passed into the HTTP request headers from a ThreadLocale, i.e. my current thread's context. Since this WebserviceContext is my custom class, you'll need to implement your own way to access your data.

提交回复
热议问题