使用多态JAX-WS Web服务参数

时间:2011-02-09 15:57:45

标签: java web-services jaxb jax-ws

我有这个简单的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 {}

我创建了一个客户端,并使用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是抽象的。

有没有办法让Rambo作为类Dog的实例解组?我有什么选择?

1 个答案:

答案 0 :(得分:7)

正如您可能已经猜到的那样,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>