I have this simple JAX-WS WebService:
@WebService
public class AnimalFeedingService {
@WebMethod
public void feed(@WebParam(name = "animal") Animal animal) {
// Whatever
}
}
@XmlSeeAlso({ Dog.class, Cat.class })
public abstract class Animal {
private double weight;
private String name;
// Also getters and setters
}
public class Dog extends Animal {}
public class Cat extends Animal {}
I create a client and call feed
with an instance of Dog
.
Animal myDog = new Dog();
myDog .setName("Rambo");
myDog .setWeight(15);
feedingServicePort.feed(myDog);
The animal in the body of the SOAP call looks like this:
<animal>
<name>Rambo</name>
<weight>15</weight>
</animal>
and I get an UnmarshallException
because Animal
is abstract.
Is there a way to have Rambo unmarshalled as an instance of class Dog
? What are my alternatives?
As you might have guessed, XML parser is not able to determine the exact subtype of animal you used when requesting because anything it sees is generic <animal>
and a set of tags that are common to all types, hence the error. What JAX-WS implementation do you use? It is the responsibility of the client to properly wrap polymorphic types when sending request. In Apache CXF (I checked your code against newest 2.3.2 version) the SOAP request body looks like this:
<animal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:dog">
<name>Rambo</name>
<weight>15.0</weight>
</animal>
The xsi:type="ns2:dog"
is crucial here. It seems like your JAX-WS client is sending incorrect request that confuses the server. Try sending this request with some other client, like SoapUI, to see whether your server reacts properly.
As I said, it works just fine with Spring/Apache CXF and exactly the same code you've provided, I only extracted Java interface to make CXF happy:
public interface AnimalFeedingService {
@WebMethod
void feed(@WebParam(name = "animal") Animal animal);
}
@WebService
@Service
public class AnimalFeedingServiceImpl implements AnimalFeedingService {
@Override
@WebMethod
public void feed(@WebParam(name = "animal") Animal animal) {
// Whatever
}
}
...and the server/client glue code:
<jaxws:endpoint implementor="#animalFeedingService" address="/animal"/>
<jaxws:client id="animalFeedingServiceClient"
serviceClass="com.blogspot.nurkiewicz.test.jaxws.AnimalFeedingService"
address="http://localhost:8080/test/animal">
</jaxws:client>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With