Skip to main content

JAXB makes a DI container

Posted by kohsuke on August 23, 2006 at 3:22 PM PDT

Some time ago, James Strachan and I had a little chat about how JAXB can be a key functionality for a dependency injection (DI) container. See his proposal at Codehaus.

The idea is, first you write a bunch of POJOs that are JAXB-enabled, like this:

package org.acme;

public class Bar {
    private int x,y;

    public int getX() { ... }
    public void setX(int x) { ... }
    public int getY() { ... }
    public void setY(int y) { ... }
}

public class Foo {
    public int a;
    public String b;
    @XmlIDREF
    public Object c;
}

Notice that the Foo bean has one @XmlIDREF property. This is where the JAXB "DI container" will inject the variable as described in the XML file.

The XML config file will look like this:

<br /><container><br />  <value id="foo"><br />    <Foo xmlns="java:org.acme"><br />      <a>5</a><br />      <b>text</b><br />      <c>bar</c><cs_comment  this is IDREF to the 'bar' bean down below --><br />    </Foo><br />  </value><br />  <value id="bar"><br />    <Bar xmlns="java:org.acme"><br />      <x>3</x><br />      <y>5</y><br />    </Bar><br />  </value><br /></container><br />

and represent the Java classes above. Notice that I'm using the package name as the namespace URI and the class name as the element local name. This is how the container code determines which class to instanciate.
Also notice that the element has the C field pointing to the bar bean by means of IDREF. So when our little DI container reads this file, it will assign an instance of the corresponding Bar object there. Isn't that nice?

Anyway, the point I'm trying to convey is not that this is a full DI container. The highlight is that this is done by utilizing two general-purpose hooks in the RI. One is the pluggable ID handling,
which lets the application code manage what IDREF resolves to what ID, and this has been in the RI for a while.

The other is a new addition in the upcoming JAXB RI 2.1, which is the mechanism for you to tell JAXB lazily what classes to unmarshal. The standard way in JAXB is to pass in all the classes upfront to JAXBContext.newInstance() method. This makes it impossible for JAXB to be used in a situation like this, because unless you read the document, you can't tell what classes are used there.

The new addition ClassResolver come to rescue. You can set one to the Unmarshaller, and when JAXB hits an element that it doesn't understand, it asks you to tell the class that will handle that element. Once your code returns that, the JAXB RI will continue unmarshalling by using that class.

There are many other uses for these two features. You can download the RI that includes this feature from here. Let me know how you think of this feature, so that we can get it right before 2.1 ships!

Related Topics >>