Coming to think about it, there are two questions or observations regarding my sample code:
(1) Why is setting the ENDPOINT in the main thread affecting the execution of the two threads that are created later on? (Actually I see that in the code -- there is an EchoContext in class ClientImpl that reflects thread-local modifications in a global map called "currentRequestContext" -- but I don't quite get the benefit from it.) (2) Doing the exact same thing with custom soap headers like client.getRequestContext().put(Header.HEADER_LIST, List<Header>) works; in a 2nd invocation I can remove the header list and it is indeed removed. Please let me know if I need to clarify on anything! Bernd PS: There is small mistake in the last try-catch block in the code. Instead of "callback1.get()" it should read "callback2.get()". Am Samstag, 29. August 2009 21:12:35 schrieb Bernd Wiswedel: > 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(); > }
