My web service client creates an org.apache.cxf.endpoint.Client(Impl) at 
runtime and analyzes the input/output parameters dynamically. It re-uses the 
same ClientImpl in different threads (possibly in parallel). As different 
threads may set different endpoints on the client, I call 
client.setThreadLocalRequestContext(true) right after Client construction.

Problem is that if thread A sets 
client.getRequestContext().put(Message.ENDPOINT_ADDRESS, <someValue>) and 
thread B unsets it
client.getRequestContext().remove(Message.ENDPOINT_ADDRESS),
any invocation in thread B still sees what thread A had set before. I attach 
some sample code that hopefully helps to understand the problem better. 

Is this a bug or is setting a dedicated endpoint to be done differently? If 
not, can I workaround it?

Thanks
 Bernd

###################

/** Example code that invokes the service found in 2.2.3 release,
  * samples/java_first_jaxws (HelloWorld), launched with "mvn -Pserver" */

JaxWsDynamicClientFactory factory = 
    JaxWsDynamicClientFactory.newInstance();
final ClientImpl client = (ClientImpl)factory.createClient(
        "http://localhost:9000/helloWorld?wsdl";);
client.setThreadLocalRequestContext(true);

try {
    /* Workaround https://issues.apache.org/jira/browse/CXF-2409 */
    Field outFaultObserverField = 
        ClientImpl.class.getDeclaredField("outFaultObserver");
    outFaultObserverField.setAccessible(true);
    Field busField = ClientImpl.class.getDeclaredField("bus");
    busField.setAccessible(true);
    Bus bus = (Bus)busField.get(client);
    outFaultObserverField.set(client, new ClientOutFaultObserver(bus));
} catch (Exception e) {
    e.printStackTrace();
}


/* 1st invocation with overwritten endpoint address */
Map<String, Object> reqContext = new HashMap<String, Object>();
String newEndpointLocation = "http://illegal.address/helloworld";;
reqContext.put(Message.ENDPOINT_ADDRESS, newEndpointLocation);
client.getRequestContext().putAll(reqContext);
final ClientCallback callback1 = new ClientCallback();
new Thread(new Runnable() { 
    /** {...@inheritdoc} */
    @Override
    public void run() {
        try {
            client.invoke(callback1, "sayHi", "James");
        } catch (Fault fault) {
            // expected java.net.UnknownHostException: illegal.address
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}, "Submitter-1").start();
try {
    System.out.println(callback1.get()[0]);
} catch (ExecutionException ee) {
    // expected error ...  (same as in run(), wrapped in ExecException)
} catch (Exception e1) {
    e1.printStackTrace();
}


/* 2nd invocation with reset endpoint address */
client.getRequestContext().remove(Message.ENDPOINT_ADDRESS);
final ClientCallback callback2 = new ClientCallback();
new Thread(new Runnable() { 
    /** {...@inheritdoc} */
    @Override
    public void run() {
        try {
            client.invoke(callback2, "sayHi", "Joe");
        } catch (Fault fault) {
            // UNEXPECTED java.net.UnknownHostException
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}, "Submitter-2").start();
try {
    // this should print "Hello Joe" but it doesn't
    System.out.println(callback1.get()[0]);
} catch (ExecutionException ee) {
    // again, unexpected.
    ee.printStackTrace();
} catch (Exception e1) {
    e1.printStackTrace();
}

Reply via email to