tags:

views:

4243

answers:

4

I'm trying to generate Java classes from the FpML (Finanial Products Markup Language) version 4.5. A ton of code is generated, but I cannot use it. Trying to serialize a simple document I get this:

javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.SAXException2: unable to marshal type "org.fpml._2008.fpml_4_5.PositionReport" as an element because it is missing an @XmlRootElement annotation]

In fact no classses have the @XmlRootElement annotation, so what can I be doing wrong?. I'm pointing xjc (JAXB 2.1) to fpml-main-4-5.xsd, which then includes all types.

A: 

This appears to be by design. I'm not allowd to add hyperlinks, but if you search on the Java forums there is a thread about this.

I'm a bit baffled too and I'm not sure what the best way is to work around this. The "simple binding" is not working for me.

+3  A: 

It's not working for us either. But we did find a widely-quoted article that adds SOME background... I'll link to it here for the sake of the next person: http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html

mcherm
This worked well for me, thank you. I also found that I was marshaling the wrong JAXB object (not the root like I thought) in the process of going through this. I forgot to create a JAXBElement and was trying to marshal just the returned object from the ObjectFactory class I had obtained from binding. This basically took care of the issue altogether (in case anyone else runs up against the same problem).
Joe
+4  A: 

To tie together what others have already stated or hinted at, the rules by which JAXB XJC decides whether or not to put the @XmlRootElement annotation on a generated class are non trivial (see this article).

@XmlRootElement exists because the JAXB runtime requires certain information in order to marshal/unmarshal a given object, specifically the XML element name and namespace. You can't just pass any old object to the Marshaller. @XmlRootElement provides this information.

The annotation is just a convenience, however - JAXB does not require it. The alternative to is to use JAXBElement wrapper objects, which provide the same information as @XmlRootElement, but in the form of an object, rather than an annotation.

However, JAXBElement objects are awkward to construct, since you need to know the XML element name and namespace, which business logic usually doesn't.

Thankfully, when XJC generates a class model, it also generates a class called ObjectFactory. This is partly there for backwards compatibility with JAXB v1, but it's also there as a place for XJC to put generated factory methods which create JAXBElement wrappers around your own objects. It handles the XML name and namespace for you, so you don't need to worry about it. You just need to look through the ObjectFactory methods (and for large schema, there can be hundreds of them) to find the one you need.

skaffman
A: 

Was anyone able to get this to work? I am having the same problem with another xsd. I have tried to add this, but it still does not create XmlRootElements

 <xs:annotation>
    <xs:appinfo>
      <jaxb:globalBindings>
        <xjc:simple />
      </jaxb:globalBindings>
    </xs:appinfo>
  </xs:annotation>

I am building the project via Maven, and had to add this as well:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.3</version>
            <configuration>
                <arguments>-extension</arguments> 
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

Regardless, in the end I still get no XmlRootElements. The beginning of the xsd looks like:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dmi="http://xml.juniper.net/dmi"
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
  jaxb:version="1.0"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
  jaxb:extensionBindingPrefixes="xjc">

 <xs:annotation>
    <xs:appinfo>
      <jaxb:globalBindings>
        <xjc:simple />
      </jaxb:globalBindings>
    </xs:appinfo>
  </xs:annotation>

<!-- create-logical-system -->
<xs:complexType name="create-logical-system">
  <xs:annotation>
    <xs:appinfo>
      <dmi:rpc-info>
        <name>Create Logical System</name>
        <avail>
          <matches>
            <match>
              <operational-mode>logical-systems</operational-mode>
              <value>false</value>
            </match>
            <match>
              <value>true</value>
            </match>
          </matches>
        </avail>
        <description>
          This command creates a new logical system
        </description>
        <rpc-reply-tag>create-logical-system-reply</rpc-reply-tag>
      </dmi:rpc-info>
    </xs:appinfo>
  </xs:annotation>
  <xs:sequence>
...

Anyone see what I am doing wrong?

wuntee