加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

Web服务 – 使用纯JAX-WS添加SOAP头对象

发布时间:2020-12-14 21:47:15 所属栏目:资源 来源:网络整理
导读:我试图使用JAX WS实现PayPal Express Checkout API的简单Web服务客户端。 PayPal Express Checkout API提供WSDL文件,我可以使用CXF的wsdl2java实用程序生成Java类。 从认证的原因,它要求为每个请求添加SOAP头。这个标题很简单,应该看起来像这样: https:/
我试图使用JAX WS实现PayPal Express Checkout API的简单Web服务客户端。 PayPal Express Checkout API提供WSDL文件,我可以使用CXF的wsdl2java实用程序生成Java类。

从认证的原因,它要求为每个请求添加SOAP头。这个标题很简单,应该看起来像这样:
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECSOAPAPIBasics#id09C3I0CF0O6

从WSDL类生成的包括ebay.apis.eblbasecomponents.CustomSecurityHeaderType类,它代表我需要添加到每个请求中的头。

所以问题是:如何将手动创建的CustomSecurityHeaderType类的实例添加到SOAP请求的头部,并考虑以下条件:

>我不是非常渴望使用com.sun。*包中的类,如答案所述:JAX-WS – Adding SOAP Headers(主要是因为不同JDK之间可能的可移植性问题)
>我不想手动将该对象编组到嵌套的javax.xml.soap.SOAPElement实例中,如下所述:
How do I add a SOAP Header using Java JAX-WS

解决方法

所以,看起来我已经找到可能的答案,而JAX-WS&来自SO的JAXB相关答案(如果有人在这些技术中有经验可以检查以下是否正确,我真的很感激):

对我来说显而易见的是在其中添加SOAP消息处理程序和SOAPMessage实例的alter头:

import javax.xml.ws.Binding;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.Handler;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.soap.SOAPHeader;
import ebay.api.paypalapi.ObjectFactory; // class generated by wsdl2java

// following class is generated by wsdl2java utility Service class
final PayPalAPIInterfaceService payPalService = new PayPalAPIInterfaceService();
final PayPalAPIAAInterface expressCheckoutPort = payPalService.getPayPalAPIAA();
final Binding binding = ((BindingProvider) expressCheckoutPort).getBinding();
List<Handler> handlersList = new ArrayList<Handler>();

// now,adding instance of Handler to handlersList which should do our job:
// creating header instance
final CustomSecurityHeaderType headerObj = new CustomSecurityHeaderType();
final UserIdPasswordType credentials = new UserIdPasswordType();
credentials.setUsername("username");
credentials.setPassword("password");
credentials.setSignature("signature");
headerObj.setCredentials(credentials);

// bookmark #1 - please read explanation after code
final ObjectFactory objectFactory = new ObjectFactory();
// creating JAXBElement from headerObj
final JAXBElement<CustomSecurityHeaderType> requesterCredentials = objectFactory.createRequesterCredentials(headerObj);

handlersList.add(new SOAPHandler<SOAPMessageContext>() {
    @Override
    public boolean handleMessage(final SOAPMessageContext context) {        
        try {
            // checking whether handled message is outbound one as per Martin Strauss answer
            final Boolean outbound = (Boolean) context.get("javax.xml.ws.handler.message.outbound");
            if (outbound != null && outbound) {
                // obtaining marshaller which should marshal instance to xml
                final Marshaller marshaller = JAXBContext.newInstance(CustomSecurityHeaderType.class).createMarshaller();
                // adding header because otherwise it's null
                final SOAPHeader soapHeader = context.getMessage().getSOAPPart().getEnvelope().addHeader();
                // marshalling instance (appending) to SOAP header's xml node
                marshaller.marshal(requesterCredentials,soapHeader);
            }
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
        return true;
    }

    // ... default implementations of other methods go here

});

// as per Jean-Bernard Pellerin's comment setting handlerChain list here,after all handlers were added to list
binding.setHandlerChain(handlersList);

书签#1的说明:
应该不是头文件本身,而是代表该对象的JAXBElement,否则会得到异常。应该使用从WSDL生成的一个ObjectFactory类,以从原始对象创建所需的JAXBElement实例。
(感谢@skaffman的答案:No @XmlRootElement generated by JAXB)

还应该参考马丁·斯特劳斯(Martin Straus)的答案,这个答案扩展了这一点

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读