Search code examples
javasoapjaxbapache-camelcxf-codegen-plugin

Getting a list of JAXBElement where I want a list of predefined java objects


I use Apache Camel + JAXB for Soap processing. The java glasses are generated by a maven plugin called cxf-codegen-plugin.

The Problem I am facing is that when I want to use a property which is a list. In that case I will always get a list of JAXBElement instead of objects of the correct class.

Assume this given xml snipped:

<domainObjects avqxsi:type="avqsq:AssetAllocation" id="100" name="Some Name">
    <nodes>101</nodes>
    <nodes>102</nodes>
  </domainObjects>

Now all the "nodes" are ids of different domain objects of type AANode. So in the xsd it is defined like so:

<xsd:complexType name="AssetAllocation">
    <xsd:complexContent>
      <xsd:extension base="avqsq:DomainObject">
        <xsd:sequence>
          <xsd:element ecore:reference="avqsq:AANode" maxOccurs="unbounded" name="nodes" type="xsd:IDREF"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>

And I have defined some bindings.xml:

<jaxb:bindings node="xsd:complexType[@name='AssetAllocation']//xsd:element[@name='nodes']">
            <jaxb:property>
                <jaxb:baseType name="my.api.xsd.AANode"/>
            </jaxb:property>
        </jaxb:bindings>

What I want is a POJO property like this:

@XmlElementRef(name = "nodes")
protected List<AANode> nodes;

But what I actually get at runtime is a List<JAXBElement<AANode>> which leads into a ClassCastException.

EDIT 1: I have missed the fact that the cxf-codegen framework is generating a class where you clearly can see that the property is annotated with JAXBElement.class which i think is wrong. Interestingly changing the annotation by hand to AANode.class will fail with an IllegalAnnotationException: AANode" or any of its subclasses are not known to this context.

public class AssetAllocation
    extends DomainObject
    implements Serializable, Equals, HashCode, ToString
{

    @XmlElementRef(name = "nodes", type = JAXBElement.class)
    protected List<AANode> nodes;

Solution

  • In fact the wsdl2java generates classes with wrong annotations. Instead of

    @XmlElementRef(name = "nodes", type = JAXBElement.class)
    protected List<AANode> nodes;
    

    One would expect to have:

    @XmlIDREF
    protected List<AANode> nodes;
    

    I was not able to manage this by bindings.xml. So my final solution is that I use a Byte-Code manipulation to fix the annotations. That way I do not have to mess around with the generated classes or with the generator itself.