Friday, May 2, 2008

JAXB and the nasty @XmlID

I wonder why the developers of JAXB decided to make the @XmlID annotations support Strings only? You would think that a String or any primitive type would've been acceptable. The Javadoc of XmlID states:
The usage is subject to the following constraints:
  • At most one field or property in a class can be annotated with @XmlID.
  • The JavaBean property's type must be java.lang.String.
  • The only other mapping annotations that can be used with @XmlID are:@XmlElement and @XmlAttribute
The other property annotations like XmlAttribute and XmlElement support primitives and wrappers. This of course means if you are using JAXB to XML Serialize a JPA Entity, your primary ID key needs to be a string instead of a Integer/Long value. JPA Persistence will still treat this as an integer in your datastore if you have the @GeneratedValue annotation set, so at least from this perspective your data model does not need to change. The advantage of using the @XmlID annotation is it allows you to use the @XmlIDREF tag in other Entities (meaning the entire entity is not XML Serialized only it's @XmlID value. Here is a simple example:
   @Entity @XmlRootElement
   public class Company implements Serializable {
      @Id @Column(name="company_id") @GeneratedValue
      @XmlAttribute @XmlID
      private String id;

      // ... setters, getters and other methods.
   }

   @Entity @XmlRootElement
   public class Employee implements Serializable {
      @Id @GeneratedValue
      @XmlAttribute @XmlID
      private String id;
   
      @JoinColumn(name="COMPANY_REF", referencedColumnName = "company_id")
      @ManyToOne(optional=false)
      @XmlIDREF
      private Company worksfor;

      // ... setters and other methods
   }

Now if we marshall an Employee with an id of "50" who works for a company with an id of "20", the resulting XML would look something like the following:

   <employee id="50">
      <worksfor>20</worksfor>
   <employee>

1 comment:

Wolfgang said...

>I wonder why the developers of JAXB decided to make the @XmlID annotations support Strings only?

Have you had a look at the XML Schema language definition? A JAXB property tagged with @XmlID corresponds to the XML Schema type 'xs:ID' which is a subtype of 'xs:NCName' and thus cannot contain a decimal value (i.e it must not start with [0-9]).
This means a value for @XmlID must be a string if you want to create a valid XML document.
However, in your case you probably don't want to validate your XML entities. JAXB doesn't care about conformance to xs:ID as long as you don't enable validation.

Kind regards,

Wolfgang