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