1

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>
Marek-A-
  • 474
  • 12
  • 29

1 Answers1

1

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);
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • thank you for response, you are right example is old, but most complex I found for asynchronous WS with ws-addressing. Also the changing package name to *.internal.ws.* is not good... – Marek-A- Nov 24 '16 at 09:44
  • ... to your hint, I checked the MessageContext object has not null value and contains correct payload, but there is not any put of HeaderList (type) as a property within the message context. It doesn't mind for reading the ID and was:To, but I'm not able to construct EndpointReference anyhow, that's real problem for me. Therefore I need HeaderList to call: getHeaders().getReplyTo(...) – Marek-A- Nov 24 '16 at 10:12
  • I think you could inject `javax.xml.soap.SOAPMessage`and use `getHeader` to get all the SOAP headers http://docs.oracle.com/javaee/5/api/javax/xml/soap/SOAPMessage.html, and extract the `replyTo`. I am not sure if you could cast `Message m= ((WrappedMessageContext)messageContext).getWrappedMessage()`to `SOAPMessage` or you will need an interceptor – pedrofb Nov 24 '16 at 10:33
  • I think it won't be the problem extract the information from SOAPHeader, but I do not know how to create an EndpointReference object by this information. – Marek-A- Nov 24 '16 at 11:15
  • 1
    Uff, without using those `com.sun.*` classes, seems creating and `EndpointReference` is not trivial. Check this ticket http://stackoverflow.com/questions/10813220/how-to-specify-replyto-endpointreference-in-a-jax-ws-client and this test code of CXF which creates Endpoints using different mechanism http://alvinalexander.com/java/jwarehouse/apache-cxf/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/EndpointReferenceTest.java.shtml – pedrofb Nov 24 '16 at 11:36
  • Thanks pedrofb, I'll start to check the examples, this seems to be covering what I need ... moreover it may solve also my next problem, originally we use the Provider implementation and I won't have any WS type implementations as in case of original example .getCorrelatedPort(...) call, so that's good these examples use only URIs contained in wsa:* header elements. – Marek-A- Nov 24 '16 at 16:06