JAXB如何在子类数组中强制xsi:type? (JBoss 4.2.3)

时间:2011-07-06 10:53:43

标签: jboss jaxb

(请注意;我对网络服务是全新的,所以以下内容可能是愚蠢的/不正确但请耐心等待)

在我的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,因为我不太喜欢单个参数限制,但是现在这个工作正常。

0 个答案:

没有答案