There is an excellent article by Young Yang that explains how to use wsimport to create web service client artifacts that have asynchronous web service calls. Asynchrony requires that the WSDL has the tag
<enableAsyncMapping>true</enableAsyncMapping>
in its bindings section. If you are using the bottom-up approach with JAX-WS annotated Java classes you can't do this directly in the WSDL because the WSDL is a generated artifact on the web server. Instead you use build tools like Ant or Maven to include this binding when wsimport is executed on the WSDL.
The generated client artifacts have asynchronous method calls that return a
Future<?>
or a
Response
which is a Future.
My question after reading Yang's article is why not just roll my own asynchronous web service calls using Executors and Futures. Do the artifacts created by wsimport offer some advantage that I can't see over a roll-your-own approach?
If anyone has experience or insight with both approaches I would appreciate your feedback.
In theory, the generated asynchronous clients wouldn't need to block threads. By passing an AsyncHandler, the system can use NIO to register for an event when the web service call is complete, and it can call that handler. No threads need to block at all.
If you put your synchronous web service call into an executor, it will still end up blocking a thread until the result arrives, although at least this blocking is limited to the thread pool in the executor.
As soon as you have many hundreds of threads floating around, your system performance will degrade due to context switching.
Whether the web service library under the hood actually uses NIO is another matter. It doesn't appear to be required by the JAX-WS specification. Using JDK 1.6 and setting a break point server side, I set 100 clients off to call the server. Using JVisualVM I attached to the client and could see that it had created one new thread per call to the server. Rubbish!
Looking around on the web I found that Apache CXF supports limiting the pool of threads used in async calls. Sure enough, using a client generated with CXF and putting the right libraries on the classpath as discussed here, a retest showed that only 25 threads were being used.
So why use the jax-ws API rather than build your own? Because building your own takes more work ;-)
I know that it does not reach the prompted question, but just complementing one information included on question:
"Instead you use build tools like Ant or Maven to include this binding when wsimport is executed on the WSDL."
It is possible generate the asynchronous client by a adding a custom xml file using the option -b to the wsimport:
Example:
The customAsync.xml content:
It is just one more way to generate asynchronous client beyond by using ant or maven :)