views:

421

answers:

2

I have a JAX-RPC (Java) web service that needs to return a complex polymorphic value. To be more specific, the class structure is something like this:

abstract class Child {
}

class Question extends Child {
    private String name;
    // other fields, getters, and setters
}

class Section extends Child {
    private String label;
    private Child[] children;
    // getters and setters
}

class Quiz {
    private Child[] elements;
    // getter and setter
}

My web service has a method that returns a Quiz, which of course may contain Questions and Sections which may contain Questions and other Sections, and so on and so forth. However, when I generate the WSDL, only Child and Quiz make it in. When I call the web service, I get back a Quiz element with the right number of children, but they're all Child elements, and they're all empty.

Is there a good way to make this work, short of just returning XML as a String?

Before anyone asks, due to circumstances beyond my control, I cannot use JAX-WS.

+1  A: 

I don't think JAX-RPC supports polymorphism in that way. I had a similar problem, and had to work around it by creating a class that had just two members - one for each of the two classes that could possibly be returned - and only populating one depending on the type I wanted to return. So in your case:

class Child 
{
    private Section section;
    private Question question;

   // Constructor, etc...
}

class Question 
{
    private String name;
    // other fields, getters, and setters
}

class Section 
{
    private String label;
    private Child[] children;
    // getters and setters
}

class Quiz 
{
    private Child[] elements;
    // getter and setter
}

Which requires the client to check which member of child is populated, and is horribly ugly, I know.

alexmcchessers
It is hacktastic, but it's probably the best way to do it and still use Java objects. Now I just have to decide whether it's better to do it that way or go plain XML.
Adam Crume
A: 

Maybe someone is still looking for it, it can be done in axis 1.4:

  1. Add next line into your <globalConfiguration> section of axis web service deployment file (wsdd):

    <parameter name="emitAllTypesInWSDL" value="true" />

  2. Modify your <axis-java2wsdl...> task in ant build file to include 'extraClasses':

    <axis-java2wsdl ... extraClasses="..."></axis-java2wsdl>

    In extraClasses mention all classes which will be passed, since axis aren't able to guess which childs you'll be passing/returning as parameters.

Done, now you can pass derivated classes in methods accepts parent classes. Etc: // server side class A { ...}

class B extends A {...}

class C extends A {...}

//ws

class wsAxis { public void processPolymorphCall(A obj); }

// client side

wsAxis.processPolymorphCall(new C()); // this will work now, as much as returning derivated classes in place of base class.

s.bombic