使用 apache CXF 和 WS-Adressing 的异步 JAX-WS Web 服务,属性 JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY 未启动

Posted

技术标签:

【中文标题】使用 apache CXF 和 WS-Adressing 的异步 JAX-WS Web 服务,属性 JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY 未启动【英文标题】:Asynchronous JAX-WS webservice using apache CXF and WS-Adressing, property JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY not initiated 【发布时间】:2017-04-07 17:22:57 【问题描述】:

我在以下blog 中描述的示例 Web 服务的 MessageContext 中启动 JAXWSProperties 时遇到问题

getHeaders() 方法中有帮助类初始化 HeaderList 对象:

import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
import com.sun.xml.internal.ws.api.message.HeaderList;
import com.sun.xml.internal.ws.api.message.Headers;
import com.sun.xml.internal.ws.developer.JAXWSProperties;
import com.sun.xml.internal.ws.developer.WSBindingProvider;

import javax.xml.ws.EndpointReference;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceContext;

public final class CorrelationHelper<S extends Service> 

private WebServiceContext wsc;
private S service;

public CorrelationHelper(S service, WebServiceContext wsc) 
    this.service = service;
    this.wsc = wsc;


private HeaderList getHeaders() 
    return (HeaderList)wsc.getMessageContext().get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);


public <P> P getCorrelatedPort(Class<P> portType) 
    P port = service.getPort(getReplyTo(), portType);
    ((WSBindingProvider)port).setOutboundHeaders(Headers.create(AddressingVersion.W3C.relatesToTag,
                                                                getMessageId()));
    return port;


private EndpointReference getReplyTo() 
    return getHeaders().getReplyTo(AddressingVersion.W3C,
                                   SOAPVersion.SOAP_11).toSpec();



private String getMessageId() 
    return getHeaders().getMessageID(AddressingVersion.W3C,
                                     SOAPVersion.SOAP_11);


这个助手是从服务实现中调用的:

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.soap.Addressing;

import dev.home.examples.jobprocessor.client.JobProcessorNotify;
import dev.home.examples.jobprocessor.client.JobProcessorNotify_Service;
import dev.home.examples.jobprocessor.client.JobReplyType;
import dev.home.examples.jobprocessor.handlers.CorrelationHelper;
import dev.home.examples.jobprocessor.types.JobType;

@WebService(serviceName = "JobProcessor",
            targetNamespace = "http://examples.home.dev/jobprocessor",
            portName = "jobProcessor",
            endpointInterface = "dev.home.examples.jobprocessor.ws.JobProcessor")
@HandlerChain(file = "JobProcessor-HandlerChain.xml")
@Addressing(required = true)
public class JobProcessorImpl 
//...
public void processJob(JobType job) 

    // do processing
    int seconds = doJob();

    // prepare reply message
    JobReplyType jobReply = new JobReplyType();
    jobReply.setJobId(job.getJobId());
    jobReply.setResult(String.format("Job payload %s processed in %d seconds!",
                                     job.getPayload(), seconds));

    // do correlation and perform the callback
    JobProcessorNotify jobProcessorNotify =
        correlationHelper.getCorrelatedPort(JobProcessorNotify.class);
    jobProcessorNotify.replyFinishedJob(jobReply);


在 getReplyTo() 期间未启动 HeaderList 并且返回为 null:

(HeaderList)wsc.getMessageContext().get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY)


Caused by: java.lang.NullPointerException
    at dev.home.examples.jobprocessor.handlers.CorrelationHelper.getReplyTo(CorrelationHelper.java:67)
    at dev.home.examples.jobprocessor.handlers.CorrelationHelper.getCorrelatedPort(CorrelationHelper.java:56)
    at dev.home.examples.jobprocessor.ws.JobProcessorImpl.processJob(JobProcessorImpl.java:61)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180)
    at org.apache.cxf.jaxws.JAXWSMethodInvoker.performInvocation(JAXWSMethodInvoker.java:66)
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
    ... 17 more

虽然 SOAP 数据 Header 包含所有数据:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://examples.home.dev/jobprocessor/types">
   <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing"><wsa:Action>http://examples.home.dev/jobprocessor/processJob</wsa:Action><wsa:ReplyTo><wsa:Address>http://CZ407032:8088/mockJobProcessorNotify</wsa:Address></wsa:ReplyTo><wsa:MessageID>uuid:96dd09e2-c448-47c0-902f-7eb95421e232</wsa:MessageID><wsa:To>http://CZ407032:8088/JobProcessor</wsa:To></soapenv:Header>
   <soapenv:Body>
      ...
   </soapenv:Body></soapenv:Envelope>

【问题讨论】:

【参考方案1】:

您正在使用属性INBOUND_HEADER_LIST_PROPERTY。阅读JAX-WS documentation,显示令人不快的警告

此属性是实验性的,如有更改,恕不另行通知。

HeaderListJAXWSPropertiescom.sun.xml.internal.ws.* 包中的类。你真的要使用这个吗?该博客的日期为 2012 年,可能是行为发生了变化

检查此简单代码是否返回非空对象(在您的服务中注入 messageContext@Resource 之后)

HeaderList hl = (HeaderList) messageContext.get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);

【讨论】:

谢谢你的回复,你是对的例子是旧的,但我发现最复杂的异步 WS 与 ws-addressing。将包名称更改为 .internal.ws. 也不好... ...根据您的提示,我检查了 MessageContext 对象没有空值并且包含正确的有效负载,但是在消息上下文中没有任何 HeaderList (类型)作为属性。它不介意读取 ID 并且是:To,但无论如何我无法构造 EndpointReference,这对我来说是真正的问题。因此我需要 HeaderList 来调用:getHeaders().getReplyTo(...) 我认为您可以注入javax.xml.soap.SOAPMessage并使用getHeader 来获取所有SOAP 标头docs.oracle.com/javaee/5/api/javax/xml/soap/SOAPMessage.html,然后提取replyTo。我不确定你是否可以将 Message m= ((WrappedMessageContext)messageContext).getWrappedMessage() 转换为 SOAPMessage 或者你需要一个拦截器 我认为从 SOAPHeader 中提取信息不会有问题,但我不知道如何通过这些信息创建 EndpointReference 对象。 Uff,不使用那些 com.sun.* 类,似乎创建和 EndpointReference 不是微不足道的。检查这张票***.com/questions/10813220/… 和这个CXF 的测试代码,它使用不同的机制创建端点alvinalexander.com/java/jwarehouse/apache-cxf/rt/frontend/jaxws/…

以上是关于使用 apache CXF 和 WS-Adressing 的异步 JAX-WS Web 服务,属性 JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY 未启动的主要内容,如果未能解决你的问题,请参考以下文章

使用apache cxf和maven我得到的代码看起来不正确

apache CXF wsdl2java工具的使用

将 CXF 与 Apache Camel 一起使用时,如何设置 WS-Addressing MessageId 标头?

cxf 客户端和服务端代码生成

使用Apache CXF根据wsdl文件生成代码

Apache CXF 中基于 WebSocket 的 SOAP?