Implementing Builders with JAXB generated objects

While JAXB is a good method of mapping XML into Java objects, if your schema’s are large or complex, generating the required Object graph prior to marshaling into XML can be both tedious and error prone due to the large amount of ‘boiler plate’ code of creating an object, calling accessor methods to set the values etc.

A common pattern for easing this sort of thing is known as the Builder pattern where you either have a common object holding configuration and then it builds the objects for you, or a set of objects each configured with the information and when required then build the final Object graph.

Previously however, this involved writing these builder classes manually once you have generated the model from a schema, however retepTools provides a JAXB plugin which, with a little configuration within the bindings will automatically generate these builders for you.

First an example of a simple pair of objects to be generated by JAXB – this is an abridged version of the jabber:client namespace in XMPP:

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='jabber:client'
    xmlns='jabber:client'
    elementFormDefault='qualified'>

  <xs:element name='message'>
     <xs:complexType>
        <xs:sequence>
          <xs:choice minOccurs='0' maxOccurs='unbounded'>
            <xs:element ref='subject'/>
            <xs:element ref='body'/>
          </xs:choice>
        </xs:sequence>
        <xs:attribute name='from' type='xs:string' use='optional'/>
        <xs:attribute name='from' type='xs:string' use='optional'/>
     </xs:complexType>
  </xs:element>

  <xs:element name='body'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='nonEmptyString'>
          <xs:attribute ref='xml:lang' use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='subject'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='nonEmptyString'>
          <xs:attribute ref='xml:lang' use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name='nonEmptyString'>
    <xs:restriction base='xs:string'>
      <xs:minLength value='1'/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>

Now if run through JAXB this would generate three classes: Message, Body and Subject. With this default model you would have to do something like the following to create a valid Message:

Message message = new Message();
message.setFrom( "juliet@example.com/balcony" );
message.setTo( "romeo@example.net" );

Body body = new Body();
body.getBodyOrSubject().add( "Wherefore art thou, Romeo?" );
message.setBody( body );

Now with this simple example thats fine, but imagine something where your model is far more complex, or worse can contain arbitary namespaces as children such as in XMPP where Message can contain objects within any namespace?

This is where Builders become useful. Imagine the above being converted into this:

Message message = new MessageBuilder().
	setFrom( "juliet@example.com/balcony" ).
	setTo( "romeo@example.net" ).
	addBody( new BodyBuilder().
		 setValue( "Wherefore art thou, Romeo?") ).
	build();

Although at first this may look similar to the standard way, the builders break the code into more manageable chunks. The builders themselves can be reused, so if you are sending multiple messages then you could change the above code to:

MessageBuilder builder = new MessageBuilder().
	setFrom( "juliet@example.com/balcony" ).
	addBody( new BodyBuilder().
		 setValue( "Wherefore art thou, Romeo?") );

Message message1 = builder.setTo( "romeo@example.net" ).build();

Message message2 = builder.setTo( "tybalt@example.com/cousin" ).build();

As you can see, the use of builders becomes apparent, we created two Message objects with a single change between them in a lot less code.

On the next page we’ll configure maven to build these builders.

About these ads

3 thoughts on “Implementing Builders with JAXB generated objects

  1. Ryan Gardner says:

    This looks really cool. I am having some trouble getting it working – any idea what it means when it says:

    “[ERROR] compiler was unable to honor this retep:builder customization. It is attached to a wrong place, or its inconsistent with other bindings.”?

    I’ve got basically the same setup as what you have here.

  2. Asaf Mesika says:

    Looks great, until you reach the point of defining binding for *each* complexType

  3. You make a great case for builders and how its better to generate them straight from the schema rather than manually extend classes. Is retepTools still active/functional with a semi-latest version of maven-jaxb2-plugin from 2013?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 1,767 other followers

%d bloggers like this: