Akom's Tech Ruminations

Various tech outbursts - code and solutions to practical problems
Java

Convincing JAX-WS on Axis2 1.4 to handle overloaded web service methods

Posted by Akom • Saturday, August 16. 2008 • Category: Java

This week I found myself in one of those situations...



I had initially implemented corporate web services in Axis2 1.2, using ADB data binding, starting with a WSDL. Only problem is - the WSDL I had to reimplement came from .NET, sometime around 2001... when overloading must have seemed like a good idea. Since then it's been abolished by just about everyone, including of course the current WSDL specifications. Moreover, the WSDL was most likely auto-generated by .NET with no regard for how manageable it would be. Yes, this is an experience infused with "ArrayOfAnyType", <anytype xsd:type="string">, and other such pearls.



I can't say that ADB handled overloaded methods


too well, but with the ability to hack up my auto-generated Message Receiver any way I wanted - I could easily customize behaviour depending on the incoming action.



But I wanted to get away from the ADB hell of insane data structures, pull parsers and a whole slew of other acronyms that were just ... well, cumbersome. Maybe I just don't understand the beauty of the whole thing, but JAX-WS was sounding better and better, reviews raving about it and it promising nice, clean, annotated style of implementation. So I plunged in.



Axis2 now supports JAX-WS, and I had written some interesting cross-service/cross-module containers for statistics reporting and various cached DB resources that I wanted to continue to use... not to mention various JSP's I hacked in to AXIS's own axis2-web directory in my packaging steps... So I decided to go with axis2+jax-ws.



To make a long story short:



  1. I used wsimport without issues and it produced very clean annotated beans and an interface for me to implement, with both signatures for my overloaded methods.
  2. I eventually got it up and running, and soon was greeted with an "overloaded methods are not supported" message. Bummer.


I was determined. I wanted JAX-WS in axis2.



I set up the entire code base in Eclipse and stepped through the execution. Eventually I landed in the Utils class, staring at the following code: modules/jaxws/src/org/apache/axis2/jaxws/server/endpoint/Utils.java

167               OperationDescription[] ops = eid.getDispatchableOperation(mc.getOperationName());
  168               // TODO: Implement signature matching.  Currently only matching on the wsdl:OperationName is supported.
  169               //       That means that overloading of wsdl operations is not supported (although that's not supported in 
  170               //       WSDL 1.1 anyway).
  171               if (ops == null || ops.length == 0) {
  172                   throw ExceptionFactory.makeWebServiceException(
  173                           Messages.getMessage("oprDescrErr",mc.getOperationName().toString()));
  174               }
  175               if (ops.length > 1) {
  176                   throw ExceptionFactory.makeWebServiceException(
  177                           Messages.getMessage("oprDescrErr1",mc.getOperationName().toString()));
  178               }
 



After some thinking about possible ways to inject modifications to this method from my own code, I surrendered to the hacky approach as the most efficient, and came up with the following revisions:



167 
168             OperationDescription[] ops = eid.getDispatchableOperation(mc.getOperationName());
169             // TODO: Implement signature matching.  Currently only matching on the wsdl:OperationName is supported.
170             //       That means that overloading of wsdl operations is not supported (although that's not supported in 
171             //       WSDL 1.1 anyway).
172             if (ops == null || ops.length == 0) {
173                 throw ExceptionFactory.makeWebServiceException(
174                     Messages.getMessage("oprDescrErr",mc.getOperationName().toString()));
175             }
176             if (ops.length > 1) {
177         String requestAction = mc.getAxisMessageContext().getOptions().getAction();
178               OperationDescription found = null;
179               for (int i = 0; found == null && i < ops.length; i++) {
180           if (ops[i] instanceof OperationDescriptionJava) {
181             String webMethodAction = ((OperationDescriptionJava)ops[i]).getAnnoWebMethodAction();
182             if (requestAction != null && webMethodAction != null && requestAction.equals(webMethodAction)) {
183               //return this one
184               found = ops[i]; 
185             }
186           }
187         }
188 
189                 if (found == null) {
190                   throw ExceptionFactory.makeWebServiceException(
191                     Messages.getMessage("oprDescrErr1",mc.getOperationName().toString()));
192                 }
193                 ops = new OperationDescription[] {found};
194             }
195             op = ops[0];
 


Download file: Utils.java



So now I am assuming that we are in java here (hmm), and assuming that the client is sending the Action through, either in header or however else. This actually works. Well at least in my testing it does.

0 Trackbacks

  1. No Trackbacks

0 Comments

Display comments as (Linear | Threaded)
  1. No comments

Add Comment


You can use [geshi lang=lang_name [,ln={y|n}]][/geshi] tags to embed source code snippets.
Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.
Markdown format allowed


Submitted comments will be subject to moderation before being displayed.