此帖旨在成为一个问题,但在其构成过程中,我想出了一个解决方案,我想分享它。
我有一个jax-ws Web服务,其中一个操作只需要一个参数,比方说它叫做AnimalParameter。问题是客户可以用他喜欢的任何动物(一次一个)调用我的服务。动物是预定义的。 我的目的是检索这个“AnicmalParameter”的内容,并调用另一个实际上每个动物只有一个操作的Web服务。
我将XmlElements与继承结合使用作为动态绑定选择,以便使用相同的bean捕获每个动物:
@XmlRootElement
public class AnimalParameter implements Serializable {
@XmlElements({
@XmlElement(name = "dog", type=Dog.class ),
@XmlElement(name = "cat", type=Cat.class )
})
protected Animal animal;
}
在我的情况下,客户端将一次调用一只动物。所以xml就像:
<animalParameter>
<dog>
...
</dog>
</animalParameter>
或:
<animalParameter>
<cat>
...
</cat>
</animalParameter>
通过以下方式将整个动物容器编组成一个字符串是相当容易的:
final Writer xmlString = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(AnimalParameter.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.marshal(animalParameter, xmlString);
我的问题是我想要打印xml只用我收到的动物(狗或猫不是整个参数)这看起来很困难,因为在编译时我不知道我的网络服务的动物用来调用。因此,即使我上面的bean能够用dog和cat绑定请求,你如何在不使用root元素的情况下将其编组为xml。我试图在我的bean中添加一个方便的方法:
@XmlRootElement
public class AnimalParameter implements Serializable
.
.
.
@XmlElement
public Animal getAnimal(){
return animal;
}
}
并使用:
JAXBContext jaxbContext = JAXBContext.newInstance(Animal.class);
jaxbMarshaller.marshal(animalParameter.getAnimal(), xmlString);
打印的xml是:
<animal>...</animal> and not the desired <cat>...</cat> or <dog>...</dog>
我的理解是,JAXB为了将xml绑定到java类/字段而使用的绑定元数据不会存储在只是运行时执行代码的任何地方。因此,java字段“animal”实际上并不知道它真正绑定到哪个xml节点。
我用这个解决了:
String animalName = animalParameter.getAnimal().getClass().getSimpleName();
JAXBContext jaxbContext = JAXBContext.newInstance(Animal.class);
jaxbMarshaller.marshal(new JAXBElement<Operation>(new QName(animalName), Animal.class, animalParameter.getAnimal()), stringWriter);