JAX-WS Dynamic Dispatch with CXF
This posts shows you how to do this completely at runtime, by using the CXF API directly.
If you are willing to bind yourself directly to the CXF API (as opposed to using the standard JAX-WS apis), you can do some nice things. It can do the steps of generating stubs, but completely at runtime. Look at this code:
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
Client client = dcf.createClient("http://host/invoicing.wsdl", DynamicClient.class.getClassLoader());
Object customerParam = Thread.currentThread().getContextClassLoader().loadClass("com.acme.invoicing.Customer").newInstance();
Method setCustIdMethod = customerParam.getClass().getMethod("setCustomerId", String.class);
setCustIdMethod.invoke(customerParam, "CUST-42");
Object[] result = client.invoke("doInvoicingOnCustomer", customerParam);
Here is a bit of explanation of what happens here:
- Calling createClient on a DynamicClientFactory instance makes CXF load the WSDL, generate stubs and compile them to class files. They are now available on the current threads context classloader.
- In this example, the invoicing.wsdl service is supposed to have a method doInvoicingOnCustomer(Customer). The wsdl will have Customer defined, which will make CXF generate a Customer class.
- You can then call loadClass method to load the Customer class and do a newInstance
- To call customer.setCustomerId(String), we reflect the method out and invoke the setter with the value "CUST-42".
- And lastly, we call the doInvoicingOnCustomer remote webservice method, giving the Customer instance as parameter
The above code binds directly to the CXF API. There is also the possibility of using the standard JAX-WS API for this. There are good examples on using the standard JAX-WS API to do dynamic calls:
- Using Dispatch and Service.Mode.MESSAGE to construct a JAX-WS dynamic call, where you have to provide the complete soap:Envelope part, of the message
- Using Dispatch and Service.Mode.PAYLOAD to construct a JAX-WS dynamic call, where you "only" have to provide the soap:Body part, of the message



3 kommentarer:
Anyone trying to use this piece of code should realize that the Client instance only needs to be created once at application startup.
I prefer the XFire/CXF way rather than the core APIs. Much nicer.
...
loadClass("com.acme.invoicing.Customer")
...
This seems to indicate that you have to know to which package the class is generated.
How can you know that before it's generated?
By looking into the wsdl.
Post a Comment