Skip to main content

Should JAXB Work With Fields or Properties?

Posted by kohsuke on March 30, 2005 at 6:33 PM PST

Introduction

JAXB 2.0 is primarily a persistence technology; it walks through a graph of POJOs, then it produces the equivalent XML representation, much like Java serialization.


We have a set of annotations you can use to tell JAXB that you do or don't want this property/field to show up in XML. For example, the following class tells JAXB that I want JAXB to access the properties, not the fields:


class Point {
  @XmlTransient private int x;
  @XmlTransient private int y;
 
  public void setX(int x) {
    if(x<0) throw new IllegalArgumentException();
    this.x = x;
  }
 
  @XmlElement
  public int getX() {
    return x;
  }
 
  public void setY(int y) {
    if(y<0) throw new IllegalArgumentException();
    this.y = y;
  }
 
  @XmlElement
  public int getY() {
    return y;
  }
}

As you see, if I'm willing to put annotations on my code, I can tell JAXB to work with any mixture of fields and properties. I can even tell JAXB that I want 'x' to be accessed via a property but 'y' should be accessed via a field, and so on. So it has the flexibility.


As a class gets bigger, it becomes tedious to put annotations on every single one of them. So we have this new annotation called 'XmlAccessorType'. I can use this annotation to say "I want JAXB to automatically look at fields" or "I want JAXB to automatically look at properties". The above class can be more concisely written as:

@XmlAccessorType(PROPERTY)
class Point {
  private int x;
  private int y;
 
  public void setX(int x) { ... }
  public int getX() { ... }
  public void setY(int y) { ... }
  public int getY() { ... }
}

@XmlAccessorType can be also put on a package to affect all the classes in that package.


Even with @XmlAccessorType, I can still use @XmlTransient, @XmlElement, or any other annotations on individual property/field. For example, I can write:

@XmlAccessorType(PROPERTY)
class Point {
  @XmlElement private int x;
  private int y;
 
  public void setX(int x) { ... }
  @XmlTransient public int getX() { ... }
  public void setY(int y) { ... }
  public int getY() { ... }
}

... so that I can have JAXB use the 'x' field and the 'y' property.


The Problem

We'd like to make JAXB very easy to use. That led us to think that we should be able to handle classes even when they are not annotated at all. So, if JAXB sees a totally un-annotated class like the following:

class Point {
  private int x;
  private int y;
 
  public void setX(int x) { ... }
  public int getX() { ... }
  public void setY(int y) { ... }
  public int getY() { ... }
}

Should JAXB work with fields by default, or should JAXB work with properties by default? Or could there in-between (like looking at public properties and fields by default)? That's the issue that I'd love to hear feedbacks.

Issues

Reduce Surprises



It's preferable for the default to work with as many POJOs as possible, so that people doesn't need to learn the JAXB annotations. If we only look at properties by default, it won't be able to deal with the following very simple class:

class Point {
  public int x;
  public int y;
}

It treats this class as if it has no data, because there's no property in this class.


Support non-bean



The look-properties-by-default approach assumes that you write Java beans with a getter/setter pair for all the data. But this is not always true. For example, it is common that you only expose the getter and not allow it to be modified (i.e., immutable fields). Sometimes objects maintain states that aren't directly settable/gettable from outside. Or sometimes you define a setter in other ways, like this:

   boolean isEnabled() { return enabled; }
   void enable() { enabled = true; }
   void disable() { enabled = false; }

It is also common to expose the same data in different ways. Think about the Calendar class. The number of getters/setters are far more than the number of actual meaningful data components. If you look properties by default, you'll get duplicates in XML.


External Contract



The other line of thinking is that properties better reflect the external contract of a class, whereas fields are more of the internal details of a class, and hence JAXB should look at properties by default, not fields.


Some people also say properties are more likely to stay compatible whereas the internal data structure of a class may change. This argument holds for classes in JDK, but I'm not sure if it applies to general developer population.


Precedences



How other existing technologies are doing? Java Serialization, which is perhaps the most successful persistence technology, is using fields. XStream and several other Java/XML persistence technology uses fields by default, too. The kong-term bean persistence technology uses properties by default, so does Hibernate. There are good precedences either way.


Conclusion

In the technology preview of the JAXB 2.0 RI, I made the default to fields. In the ED2 of the JAXB 2.0 spec, the default is set to properties. Hence the properties is going to be the default in the upcoming JAXB RI 2.0 early access.


But is properties a good default? Personally, I don't think so, but in this entry I tried to just list up all the points that were made so far. If you have anything to share, plase let us know how you think!

Related Topics >>