Asynchronous JAX-WS webservice using apache CXF and WS-Adressing, property JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY not initiated

1k views Asked by At

I've problem with initiation of JAXWSProperties in MessageContext of example webservice described on following blog

There is the helper class initiating HeaderList object in getHeaders() method:

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

this helper is called from service implementation as:

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

HeaderList is not initiated during getReplyTo() and than is returned as 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

although the SOAP data Header contains all data:

<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

There are 1 answers

6
pedrofb On

You are using the property INBOUND_HEADER_LIST_PROPERTY. Reading JAX-WS documentation, shows an unpleasant warning

THIS PROPERTY IS EXPERIMENTAL AND IS SUBJECT TO CHANGE WITHOUT NOTICE IN FUTURE.

HeaderList and JAXWSProperties are classes in com.sun.xml.internal.ws.* package. Do you really want to use this? The blog is dated in 2012, may be the behaviour has changed

Check if this simple code return a not null object (after injecting messageContext as @Resource in your service)

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