Использование полиморфных параметров веб-сервиса JAX-WS - PullRequest
10 голосов
/ 09 февраля 2011

У меня есть простой Web-сервис JAX-WS:

@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 {}

Я создаю клиента и вызываю feed с экземпляром Dog.

Animal myDog = new Dog();
myDog .setName("Rambo");
myDog .setWeight(15);
feedingServicePort.feed(myDog);

Животное втело вызова SOAP выглядит так:

<animal>
    <name>Rambo</name>
    <weight>15</weight>
</animal>

, и я получаю UnmarshallException, потому что Animal является абстрактным.

Есть ли способ заставить Рэмбо разобраться как экземпляр класса Dog?Каковы мои альтернативы?

1 Ответ

7 голосов
/ 10 февраля 2011

Как вы уже догадались, синтаксический анализатор XML не может определить точный подтип животного, который вы использовали при запросе, потому что все, что он видит, является общим <animal> и набором тегов, которые являются общими для всех типов, а следовательно, и ошибкой. Какую реализацию JAX-WS вы используете? Ответственность за правильную упаковку полиморфных типов при отправке запроса лежит на клиенте. В Apache CXF (я проверил ваш код на соответствие новейшей версии 2.3.2) тело запроса SOAP выглядит так:

<animal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:dog">
    <name>Rambo</name>
    <weight>15.0</weight>
</animal>

xsi:type="ns2:dog" имеет решающее значение здесь. Похоже, ваш клиент JAX-WS отправляет неверный запрос, который сбивает с толку сервер. Попробуйте отправить этот запрос другому клиенту, например, SoapUI, чтобы проверить, правильно ли реагирует ваш сервер.

Как я уже сказал, он отлично работает с Spring / Apache CXF и точно таким же кодом, который вы предоставили. Я извлек интерфейс Java только для того, чтобы CXF был счастлив:

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
    }
}

... и код сервера / клиента:

<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>
...