Question

I have an application which provides services using CXF's Servlet transport and Jetty 6.1. This application also needs to consume external services. All services support WS-Addressing specification (and WS-RM on top). To consume an external service, I run a generated service client from the application.

The problem is that when I provide a decoupled endpoint for the client (WS-RM needs this endpoint to receive incoming messages via a separate http connection), CXF runs another instance of Jetty server (in spite of the fact that Servlet transport (which provides services) and the client (which consumes some external service) share the same bus). I don't need two instances of Jetty (not saying that they can't run on the same HTTP port).

Is there a way I can provide a decoupled endpoint using an existing Jetty server and Servlet transport?

So far, I enable a decoupled endpoint like this:

Client client = ClientProxy.getClient(port);
HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
httpConduit.getClient().setDecoupledEndpoint(
     "http://domain.com:port/services/dec_endpoints/TestDecEndpoint");

If I provide a relative path ("/dec_endpoints/TestDecEndpoint", just like relative paths are used with provision of services via Servlet transport), HTTP conduit does not specify a full path in a SOAP message's headers so this doesn't work either (server just can't send a message to /dec_endpoints/TestDecEndpoint).

Was it helpful?

Solution

Ok, I have found a solution myself. You need to specify a relative path for decoupled endpoint and change message's addressing properties manually (after MAPAggregator interceptor, 'cause it sets up the decoupled destination) so the server can send replies to your address.

So what we have:

  1. decoupled destination using a relative path: /dec_endpoints/SomeDestination
  2. <ReplyTo> header with an absolute path: http://addr.com:port/servlet_path/dec_endpoints/SomeDestination

Here's an example how the path can be changed:

public class ReplyToInterceptor extends AbstractPhaseInterceptor<Message>
{
    public ReplyToInterceptor() {
        super(Phase.PRE_LOGICAL);
        addAfter(MAPAggregator.class.getName());
    }

    public void handleMessage(Message message) {
        AddressingProperties maps = ContextUtils.retrieveMAPs(message, false, 
           true);
        EndpointReferenceType replyTo = maps.getReplyTo();
        replyTo.getAddress().setValue(
           "http://address.com:port/servlet_path/dec_endpoints/SomeDestination");
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top