我正在尝试实现简单的网络服务客户端PayPal 快速结账 API using JAX WS. PayPal 快速结账 API提供WSDL文件,我可以使用该文件生成 Java 类CXF的wsdl2java公用事业。
从认证原因来看,需要添加SOAP 头对每个请求。这个标题非常简单,应该如下所示:
生成自WSDL课程包括ebay.apis.eblbasecomponents.CustomSecurityHeaderType代表我需要添加到每个请求中的标头的类。
所以问题是:如何添加手动创建的实例自定义安全标头类型考虑到以下条件,将类添加到 SOAP 请求的标头:
- 我不太渴望使用来自的课程com.sun.*此处答案中提到的软件包:JAX-WS - 添加 SOAP 标头 https://stackoverflow.com/questions/2322953/jax-ws-adding-soap-headers(主要是因为不同JDK之间可能存在可移植性问题)
- 我不想手动将该对象编组到nested javax.xml.soap.SOAPElement此处答案中提到的实例:如何使用 Java JAX-WS 添加 SOAP 标头 https://stackoverflow.com/questions/830691/how-do-i-add-a-soap-header-using-java-jax-ws
所以,看起来我在结合时找到了可能的答案JAX-WS & JAXB相关答案来自SO(如果有这些技术经验的人可以检查以下内容是否正确,我将不胜感激):
对我来说显而易见的事情是添加 SOAP 消息处理程序并更改 headerSOAP消息其中的实例:
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:
人们不应该封送标头对象本身,但是JAXB元素代表该对象,因为否则会出现异常。应该使用其中之一对象工厂生成的类WSDL用于创建所需的JAXB元素来自原始对象的实例。
(感谢@skaffman的回答:JAXB 没有生成 @XmlRootElement https://stackoverflow.com/questions/819720/no-xmlrootelement-generated-by-jaxb )
还应该参考Martin Straus
扩展这个答案的答案
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)