(请注意;我对网络服务是全新的,所以以下内容可能是愚蠢的/不正确但请耐心等待)
在我的WebServices'@WebMethod中,我返回一个抽象基类的数组(JBoss 4.2.3中带有JAXB注释的实体)。
显然,除非每个数组元素编码类型信息,否则这将失败......
那么如何确保JAXB添加 xsi:type 属性?
我的WebService界面有以下注释,我尝试过各种合法组合:
@SOAPBinding(style = RPC,parameterStyle = WRAPPED,use = LITERAL)
此接口上的方法采用带注释的x2参数@WebParam(name =“...”,mode = IN)
具有类似签名且不返回异构数组的其他方法可以完美地工作。
看起来JBoss使用方法签名中定义的类型来决定要加载到JAXBContext中的类 - 如果我将返回类型更改为Object [],则会抛出一个错误,指出AbstractBase类“或者它的任何超类”众所周知。“我添加了返回特定子类的伪方法,以便生成的WSDL具有所有这些的列表。
当我尝试为此编写测试时,单个元素都可以,但JAXB会为数组类型抛出错误:无法编组类型“[LAbstractBase;”作为元素,因为它缺少@XmlRootElement注释
从如下所示的代码(注意:AbstractBase,ConcreteOne和ConcreteTwo都有@XmlRootElement注释)
private static final Class<?>[] CLASSES_TO_BE_BOUND = new Class<?>[]{
//Note; adding AbstractBase[].class doesn't work either
AbstractBase.class, ConcreteOne.class, ConcreteTwo.class
};
@Test
public void testXsiTypeAttributeIsIncludedInHeterogeneousArray()
{
AbstractBase[] array = new AbstractBase[2];
array[0] = new ConcreteOne();
array[1] = new ConcreteTwo();
Marshaller marshaller = createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(array, sw);
String output = sw.toString();
Assert.assertTrue(output.contains("xsi:type=\""));
}
private Marshaller createMarshaller() throws Exception {
JAXBContext context = JAXBContext.newInstance(CLASSES_TO_BE_BOUND);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
return marshaller;
}
理想情况下,我希望能够测试与数组相关的一些位,但是在JBoss环境中获取每个元素编码的类型信息更为重要。
JBoss(4.2.3)正在做一些聪明的事情,但不是太聪明 - 它将处理数组的返回但不处理多态数组。这让我有点兴奋,因为我试图在测试中使用这种方式。
我没有尝试解决JBoss WebService问题,而是让我的测试更加全面 - 使数组成为一个简单容器类的成员,然后使用以下命令对数组的getter进行注释:
@XmlElementRefs({
@XmlElementRef(type = ConcreteOne.class),
@XmlElementRef(type = ConcreteTwo.class)
})
public AbstractBase[] getItems() { /*...*/ }
哪个有效,并且在JBoss WebService中返回它也有效!虽然我正在使用:
@SOAPBinding(style = DOCUMENT, parameterStyle = BARE, use = LITERAL)
所以它没有添加xsi:type属性,但文档节点被正确标记:
<ConcreteOne>...</ConcreteOne>
在某些时候我会将WebService更改为使用RPC,因为我不太喜欢单个参数限制,但是现在这个工作正常。