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

后端 未结 4 495
时光说笑
时光说笑 2020-12-15 01:08

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: <

相关标签:
4条回答
  • 2020-12-15 01:47

    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.

    0 讨论(0)
  • 2020-12-15 01:47

    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);
    
    0 讨论(0)
  • 2020-12-15 01:59

    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!

    0 讨论(0)
  • 2020-12-15 02:00

    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();
                 }
             };
         }
    }
    
    0 讨论(0)
提交回复
热议问题