manash
manash

Reputation: 7106

JAXB doesn't annotate with XmlRootElement

When I generate code from the following schema, two classes are created, A and B. But, these two classes are not annotated by @XmlRootElement, so I get an error when I try to marshal an instance of B.

I've looked on the web, I tried the solution using custom bindings (<xjc: simple/>) but it doesn't work. It seems that an element of type B must be defined in the schema in order for this solution to work.

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:ns="com:mycomp:service" xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="com:mycomp:service"
    elementFormDefault="qualified" xml:lang="EN">
    <complexType name="A" abstract="true">
        <sequence>
            <element name="a1" type="string" />
        <element name="a2" type="string" />
        </sequence>
    </complexType>
    <complexType name="B">
        <complexContent>
            <extension base="ns:A">
            <sequence>
                <element name="b1" type="string" />
            </sequence>
        </extension>
        </complexContent>
    </complexType>
</schema>

Thanks

Upvotes: 2

Views: 1760

Answers (3)

Ian Roberts
Ian Roberts

Reputation: 122364

That is correct, because your schema doesn't declare any root elements, only types. If you want to marshal an instance of one of your @XmlType-annotated classes you will need to wrap that instance in a JAXBElement in order to tell the marshaller what element name to use:

// create context from the package name that contains your generated classes
JAXBContext ctx = JAXBContext.newInstance("com.mycomp.service");
Marshaller marshaller = ctx.createMarshaller();
marshaller.marshal(new JAXBElement<B>(new QName("com:mycomp:service", "someB"),
      B.class, instanceOfB), outputStream);

This would produce something like

<someB xmlns="com.mycomp.service">
  <a1>foo</a1>
  <a2>bar</a2>
  <b1>baz</b1>
</someB>

Edit: you've commented that you're not doing the marshalling yourself but rather returning an object for a REST framework to marshal on your behalf. You may be able to use the same trick there by declaring your operation to return JAXBElement<B> instead of just B, but you're probably better off modifying the schema as suggested in other answers.

Upvotes: 1

Puce
Puce

Reputation: 38132

XJC will only generate the @XmlRootElement if the type of the top element in question (usually the single root element) is anonymous.

Eg. something like (untested):

<element name='B'>
   <complexType>
        <complexContent>
            <extension base="ns:A">
            <sequence>
                <element name="b1" type="string" />
            </sequence>
            </extension>
        </complexContent>
  </complexType>
</element>

Upvotes: 1

CAMOBAP
CAMOBAP

Reputation: 5657

You need add <element> tag to your schema

<schema xmlns:ns="com:mycomp:service" xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="com:mycomp:service"
    elementFormDefault="qualified" xml:lang="EN">
    <complexType name="A" abstract="true">
        <sequence>
            <element name="a1" type="string" />
        <element name="a2" type="string" />
        </sequence>
    </complexType>
    <complexType name="B">
        <complexContent>
            <extension base="ns:A">
                <sequence>
                    <element name="b1" type="string" />
                </sequence>
            </extension>
        </complexContent>
    </complexType>
    <element name="A" type="ns:A"/>
    <element name="B" type="ns:B"/>
</schema>

Upvotes: 0

Related Questions