简体   繁体   English

如何使用wsdl生成的java对象发出soap请求时添加soap标头

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

I generated client java objects using JAX-WS RI. 我使用JAX-WS RI生成了客户端java对象。 I am trying to make a SOAP request to a web service. 我正在尝试向Web服务发出SOAP请求。 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>username@gmail.com</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. 生成的java对象具有调用服务,创建对象和构造头的方法。 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. buildSearchAssetsParam()构造请求对象。 I created the header object as follows: 我创建了头对象,如下所示:

AuthHeader header = new AuthHeader();
header.setUser("username@gmail.com");
header.setPassword("password1");

How do I set this AuthHeader to the service request? 如何将此AuthHeader设置为服务请求?

Thanks, Venu 谢谢,Venu

Once I had the same problem. 一旦我遇到同样的问题。 I needed to modify the JAX-WS web service SOAP header at every request. 我需要在每次请求时修改JAX-WS Web服务SOAP标头。 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. 它将所需的参数添加到我的SOAP标头中,并在每个请求时调用它。 All you need to do is to modify handleMessage method to suit your needs. 您需要做的就是修改handleMessage方法以满足您的需求。

It works for me by overriding the public void setAttribute(String namespace, String localName, String value) method. 它通过重写public void setAttribute(String namespace, String localName, String value)方法为我工作。

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);

When you create your service from classess generated by cxf, add custom interceptor 当您从cxf生成的classess创建服务时,添加自定义拦截器

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. 您可以扩展AbstractSoapInterceptor以实现自定义拦截器来处理消息。

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();
             }
         };
     }
}

Yes, I did the same that Rangappa Tungal, following this example: 是的,我按照这个例子做了同样的Rangappa Tungal:

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! 链接到示例!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM