Thursday, 12 March 2009

Implementing custom types within JAXB

With JAXB it does a pretty good job in mapping between XML and Java Objects. In normal use this is fine but what happens when you need to use a custom data type for an attribute? Well JAXB supports this in binding so this article will describe this.


The originating issue that’s caused this article to be written cropped up at work earlier today where we had an issue with currency values. Over time the various programmers had naturally used a Java double to represent them but problems started to appear when some testers started to use amounts equivalent to €1.2 Billion and things started to fall apart.


Now obviously it’s bad practice to use double for monetary values (we’ve all done it at some point) due to the fact that specific values cannot be represented accurately (eg 39.995 is represented as 39.9949989[1]), it gets worse when dealing with large values. With large amounts you start to loose precision at the milli and penny levels, so adding 1¢ to the amount will fail because the double cannot handle it because of rounding errors.


So the solution is to use BigDecimal as it has arbitrary precision. With JAXB this is not a problem as it supports BigDecimal when defining an attribute with type xsd:decimal - as long as you own the xsd then it’s simply a case of changing it from xsd:double. The problem is when you don’t own the xsd, i.e. it’s an external specification. In this case you cannot change it as you would break other implementations. This is exactly where JAXB bindings[2] come into play.


Changing the object used in an attribute


In this first example taken from my xmpp project we have a series of xsd files and a single xjb file containing the bindings.


From client.xsd which defines the “jabber:client” namespace[3]:


<xs:element name='message'>

     <xs:complexType>

        <xs:sequence>

          <xs:choice minOccurs='0' maxOccurs='unbounded'>

            <xs:element ref='subject'/>

            <xs:element ref='body'/>

            <xs:element ref='thread'/>

          </xs:choice>

          <xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>

          <xs:element ref='error' minOccurs='0'/>

        </xs:sequence>

        <xs:attribute name='from' type='xs:string' use='optional'/>

        <xs:attribute name='id' type='xs:NMTOKEN' use='optional'/>

        <xs:attribute name='to' type='xs:string' use='optional'/>

       <xs:attribute ref='xml:lang' use='optional'/>

     </xs:complexType>

  </xs:element>


Now here the from and to attributes represent not just a string but a Jabber IDentifier JID which within the project is represented by the class uk.org.retep.xmpp.JID. This class ensures it’s both syntactically correct and provides access to the various components within the JID.


For JAXB to use this JID class instead of String we can either add the bindings into the original xsd or into a separate xjb file. I prefer the latter as it keeps the originals untouched so that if someone updates them then the bindings are not lost:


So to add the bindings for JID into the above message element we have the following bindings.xjb file:


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

<bindings

    xmlns=”http://java.sun.com/xml/ns/jaxb”

    xmlns:xsd=”http://www.w3.org/2001/XMLSchema”

    xmlns:retep=”http://retep.org/xml/ns/retepTools”

    version=”2.0”>

   <bindings schemaLocation="client.xsd" node="/xsd:schema/xsd:element[@name='message']/xsd:complexType/xsd:attribute[@name='from']">

        <property>

            <baseType>

                <javaType name="uk.org.retep.xmpp.JID" parseMethod="uk.org.retep.xmpp.JID.parse" printMethod="uk.org.retep.xmpp.JID.print" />

            </baseType>

        </property>

    </bindings>

    <bindings schemaLocation="client.xsd" node="/xsd:schema/xsd:element[@name='message']/xsd:complexType/xsd:attribute[@name='to']">

        <property>

            <baseType>

                <javaType name="uk.org.retep.xmpp.JID" parseMethod="uk.org.retep.xmpp.JID.parse" printMethod="uk.org.retep.xmpp.JID.print" />

            </baseType>

        </property>

    </bindings>

</bindings>


Here we define the attributes we want to change using an XPath expression and then the object we want to bind to that attribute. We also provide two methods to parse the attribute from a String to the object and to print it (from the object to a String). In this case those two methods are provided by the JID class itself but they don’t have to be.


Implementing the parse and print methods


The main things to watch out with the parse and print methods is that they have to be public static and they must handle null values. If the attribute is not present or should be a default value then they will be passed nulls:


From JID.java (abridged):


    public static JID parse( final String jid )

    {

        return jid == null ? null : new JID( jid );

    }


    public static String print( final JID jid )

    {

        return jid == null ? null : jid.toString();

    }


Back to the currency issue


Now with the currency issue which initially started off this rambling, there’s one more complication. In the specific DB the currency values are not actually stored as floats but in a custom SQL Type which I’ll call Money to protect the innocent. On the Java side there’s a similar object which uses a BigDecimal for the storage but also handles things like null’s etc. Anyhow in this case all that is required is to add a parse and print method into that class and add the equivalent bindings to the xjb file.


References

  1. Round and Round on the Daily WTF 
  2. Customising JAXB Bindings on sun.com
  3. jabber-client.xsd on xmpp.org

Sunday, 15 February 2009

The Generic Messaging API

A common use case is the routing of messages from one component within a system to another. The standard API for this type of messaging within Java is the Java Messaging Service or JMS - but that can be a bit overkill for small embedded systems or if you are implementing another existing messaging protocol like Jabber. Originating from the retepXMPP project, retepTools 9.2 introduces a core messaging API which can form the basis of many simple messaging systems.


Introduction


The Messaging API is relatively simple comprising of four main classes in the uk.org.retep.util.messaging package:


  • MessagingService - a class that forms the entry point into a messaging system for messages
  • Message - an interface defining the message that can be handled by the service
  • Component - an interface defining a component that can accept messages
  • Router - an interface defining a component that can route messages to another Router or component.


The API is totally generic so the above classes have no concept of the inplementation of an address (where messages are sent to) or the route required to send them between Routers - this is left entirely to the implementing code. The only requirement is that the implementing classes obey the contract between hashCode and equals.


The API also provides some concrete implementations of the interfaces. These implementations are themselves generic, but they are also fully concurrent allowing the implemented messaging system to operate in a fully multi-threaded environment.


The rest of this article will show how to implement a simple messaging system where a group of interacting components can pass messages comprising of simple POJO’s between themselves.


Concepts


Addressing


The first concept within the Messaging API is addressing. An address is a POJO that defines the Component that the message should be sent to. It also defines where the message was sent from if a response is required. This POJO can be any Java object. For this example we will be using java.lang.String but for more complex systems you would implement a class specifically for that purpose.


For example, in Jabber an address is known as a JID (Jabber ID) and has the form node@domain/resource (where node and resource are optional). In retepXMPP the address is implemented by a JID class which holds those three components individually allowing the messages to be routed by domain first and then by node and finally by resource.


Component


The second concept is a Component, represented by the uk.org.retep.util.messaging.Component interface. It represents a POJO that can accept a Message for some form of processing.


Route


The third concept is a Route. A route is a POJO used by a Router to determine where to send messages. Usually a Route implementation would hold the part of an address relevant to the specific Router using it. You could think of the global Domain Name System (DNS). For DNS you could have an address of “retep.org”. Then sending a messsage to that address would invove the core router using the Route “org” to send the message to the router handling “org”. That router wouild then send the message to the end Component using the Route “retep”.


Router


The final concept is a Router. A Router, represented by the uk.org.retep.util.messaging.Router interface is a specialised Component that can contain other Components. It deals with forwarding Messages to one or more Components by using Route’s.


A Simple example


To show how simple it is to setup a MessagingService, we’ll create a simple system comprising of three Components that will interact with each other when an event occurs. We’ll call these components A, B and C (yes imaginative naming here).


Address


For this example our address is a java.lang.String.


Message


The first step is to create the message. This will hold an int describing the event.


package example;


import uk.org.retep.util.messaging.message.AbstractMessage;


public class Event

        extends AbstractMessage<String>

{


    private int event;


    public int getEvent()

    {

        return event;

    }


    public void setEvent( int event )

    {

        this.event = event;

    }

}


AbstractMessage is a concrete implementation of the Message interface implementing all of it’s methods. The <String> generic defines the type of the address, in this case java.lang.String.


Components


Now for our three components. Here component A will simply send a message to B when it’s setValue() method is called. B will log that event and forward the message to C. C will then log the event itself and reply back to the originator (in this case A) with the negative value. A will then log the returned value.


package example;


import net.jcip.annotations.ThreadSafe;

import uk.org.retep.util.messaging.MessageException;

import uk.org.retep.util.messaging.component.AbstractComponent;


@ThreadSafe

public class A

        extends AbstractComponent<String, Event>

{


    public void setValue( int value )

    {

        System.out.printf( "A.setValue( %d )\n", value );

        

        Event event = new Event();

        event.setFrom( "A" );

        event.setTo( "B" );

        event.setEvent( value );

        

        try

        {

            send( event );

        }

        catch( MessageException ex )

        {

            ex.printStackTrace();

        }    }


    @Override

    public void consume( Event message )

            throws MessageException

    {

        System.out.printf( "A received event from %s: %d\n",

                           message.getFrom(),

                           message.getEvent() );

    }

}


You’ll notice that the setValue method creates a new Event, sets the from and to addresses, the value of the event and then sends the message via the send() method. Once the Component is attached to the MessagingSystem then that message will be sent on to its destination.


@ThreadSafe

public class B

        extends AbstractComponent<String, Event>

{


    @Override

    public void consume( Event event )

            throws MessageException

    {

        System.out.printf( "B received event from %s: %s\n",

                           event.getFrom(),

                           event.getEvent() );


        Event newEvent = new Event();

        newEvent.setFrom( event.getFrom() );

        newEvent.setTo( "C" );

        newEvent.setEvent( event.getEvent() );


        send( newEvent );

    }

}


@ThreadSafe

public class C

        extends AbstractComponent<String, Event>

{


    @Override

    public void consume( Event event )

            throws MessageException

    {

        System.out.printf( "C received event from %s: %s\n",

                           event.getFrom(),

                           event.getEvent() );


        Event newEvent = new Event();

        newEvent.setFrom( "C" );

        newEvent.setTo( event.getFrom() );

        newEvent.setEvent( -event.getEvent() );


        send( newEvent );

    }

}


Router and Route


Now every messaging service has a core router which accepts every message as it first enters the system. For this example we’ll use the address as the route as it’s a single keyword:


package example;


import net.jcip.annotations.ThreadSafe;

import uk.org.retep.util.messaging.router.AbstractRouter;


@ThreadSafe

public class SimpleRouter

        extends AbstractRouter<String, String>

{


    @Override

    protected String getRoute( String to )

    {

        return to;

    }

}


The Generics here define the types for the Address and the Route respectively. Now as we are using String’s then both are set to String. Also our router implements the getRoute() method which should form the Route for this instance from the to address. In this case it’s just the address, but usually you would have some other logic here.


Deploy and Run


Now all there’s left is to deploy the system and send a message:


package example;


import uk.org.retep.util.messaging.MessagingService;

import uk.org.retep.util.messaging.Router;


public class Main

{


    private Main()

    {

    }


    public static void main( String... args )

            throws Exception

    {

        Router<String, String> router = new SimpleRouter();


        MessagingService<String, String> messagingService = new MessagingService<String, String>(

                router );


        A a = new A();

        messagingService.addRoute( "A", a );

        messagingService.addRoute( "B", new B() );

        messagingService.addRoute( "C", new C() );


        messagingService.startService();


        a.setValue( 42 );

    }

}


Here we create the core Router and then the MessagingService using that router. We then create the A component and add it to the service. We then do the same for B and C. Finally we start the service, and then set the value of A to 42. When run we should then see the following as the event propagates through the system:


A.setValue( 42 )

B received event from A: 42

C received event from A: 42

A received event from C: -42


Note: C says it’s received the event from A and not B because the event’s from address is A and not B - this is from the statement newEvent.setTo( event.getFrom() ); in B.


Now with this example it’s pretty simple. We could have started the service before adding the components if we wanted to - components can be added or removed at will.


Also this example is bad in the sense that we are adding all components directly to the MessagingService. This would be correct for components routed by the core route, but say we had a router called D containing a component called D/A. The component D/A would be attached to router D and D would be connected to the messaging service.

Saturday, 14 February 2009

Validating source with Annotation Processors

The release of retepTools 9.2 this week introduces a new annotation processor which validates the use of some of the annotations provided by the library generating either compilation warnings or errors dependent upon the errors found. This article describes how that processor works and the reasons behind it’s creation.


In the previous article I wrote about problems in reading values from Annotations in super types. That issue had cropped up due to some of the rules required for this processor.


Now this processor is still in it’s early stages of development but it works and is therefore useable. The rules that follow are those it will enforce and those will not change - although I will almost certainly add more over time.


The rules


Each rule defined below follows this template:


package.Annotation


Action when violated: Compile time error/warning

Mutually excludes: package.AnotherAnnotation...

Related: package.RelatedAnnotation


The Action when violated indicates if an error or warning wouild be produced if that rule is violated.


If the Mutually excludes line is present, then a compile time error will be generated if the annotation is present on an element with any of the listed annotations.


If the Related line is present, it lists annotations that are related and can affect the outcome of this rule.


1 Concurrency RULES


The main set of rules are for concurrency. In previous versions there’s a set of annotations which inject code into the methods they annotate ensuring those methods run within a specific lock - either a standard java.util.concurrent.locks.ReentrantLock or a java.util.concurrent.locks.RentrantReadWriteLock. The problem was that without compile time checking it would be possible to mark a method in one class as being a ReadLock, but then override that method in a subclass and annotate it with WriteLock. Now this would cause an immediate deadlock.


So here are the rules enforced for concurrency:


net.jcip.annotations.NotThreadSafe


Action when violated: Compile time error

Mutually excludes: net.jcip.annotations.ThreadSafe


This annotation is still optional, however it should be declared on a class that may be used in a concurrent context to indicate that it does not use any concurrency. For example an implementation of List should be marked @NotThreadSafe, but a ConcurrentList implementation with @ThreadSafe.


When it is present, this rule will generate a compile time error if any of the concurrency annotations are used in that class. Also subclasses cannot be ThreadSafe due to this class being NotThreadSafe.


For obvious reasons this annotation is mutually exclusive with NotThreadSafe


net.jcip.annotations.ThreadSafe


Action when violated: Compile time error

Mutually excludes: net.jcip.annotations.NotThreadSafe


For all classes that use any of the concurrency annotations must now be marked as ThreadSafe. The reason behind this is to ensure that documentation indicates that the class is ThreadSafe, but also to ensure that subclasses are also ThreadSafe as they can affect the concurrency of the super class. Because of this, a subclass of a class annotated with ThreadSafe must also be marked as ThreadSafe.


For obvious reasons this annotation is mutually exclusive with NotThreadSafe


uk.org.retep.annotations.Lock


Action when violated: Compile time error or warning

Mutually excludes: uk.org.retep.annotations.ReadLock, uk.org.retep.annotations.WriteLock

Related: uk.org.retep.annotations.Contract


This annotation indicates that the method runs within a shared lock. As defined by the annotations javadoc, it injects code into the method to gain the lock, run the method body and then release the lock.


This rule ensures that:

  • The method cannot be annotated with a ReadLock or WriteLock as those annotations are mutually exclusive with this one - generates an error.
  • If the method is overridden then a warning is issued that the overridden method code will be running outside of the lock.
  • As there’s a contract defined in the javadoc for a method called lock() to be defined then that method should be annotated with @Contract( Lock.class ) to document that it’s bound by that Contract. If it is not then a warning is generated.
  • The Contract for the support lock() method that is enforced is that the method has one of the following signatures. If it does not have these signatures then an error is generated: private java.util.concurrent.locks.Lock lock(); or protected final java.util.concurrent.locks.Lock lock();
  • The class is annotated with @ThreadSafe.


uk.org.retep.annotations.ReadLock


Action when violated: Compile time error or warning

Mutually excludes: uk.org.retep.annotations.Lock, uk.org.retep.annotations.WriteLock

Related: uk.org.retep.annotations.Contract


This annotation indicates that the method runs within a shared read lock. As defined by the annotations javadoc, it injects code into the method to gain the lock, run the method body and then release the lock.


This rule ensures that:

  • The method cannot be annotated with a Lock or WriteLock as those annotations are mutually exclusive with this one - generates an error.
  • If the method is overridden then a warning is issued that the overridden method code will be running outside of the lock.
  • As there’s a contract defined in the javadoc for a method called readLock() to be defined then that method should be annotated with @Contract( ReadLock.class ) to document that it’s bound by that Contract. If it is not then a warning is generated.
  • The Contract for the support readLock() method that is enforced is that the method has one of the following signatures. If it does not have these signatures then an error is generated: private java.util.concurrent.locks.Lock readLock(); or protected final java.util.concurrent.locks.Lock readLock();
  • The class is annotated with @ThreadSafe.


uk.org.retep.annotations.WriteLock


Action when violated: Compile time error or warning

Mutually excludes: uk.org.retep.annotations.Lock, uk.org.retep.annotations.ReadLock

Related: uk.org.retep.annotations.Contract


This annotation indicates that the method runs within a shared lock. As defined by the annotations javadoc, it injects code into the method to gain the lock, run the method body and then release the lock.


This rule ensures that:

  • The method cannot be annotated with a Lock or ReadLock as those annotations are mutually exclusive with this one - generates an error.
  • If the method is overridden then a warning is issued that the overridden method code will be running outside of the lock.
  • As there’s a contract defined in the javadoc for a method called writeLock() to be defined then that method should be annotated with @Contract( WriteLock.class ) to document that it’s bound by that Contract. If it is not then a warning is generated.
  • The Contract for the support writeLock() method that is enforced is that the method has one of the following signatures. If it does not have these signatures then an error is generated: private java.util.concurrent.locks.Lock writeLock(); or protected final java.util.concurrent.locks.Lock writeLock();
  • The class is annotated with @ThreadSafe.


2 Singletons


There are two annotations provided for supporting singletons:


uk.org.retep.annotations.NoInstance


Action when violated: Compile time error

Mutually excludes: uk.org.retep.annotations.Singleton


A class marked with NoInstance implies that there can be no instance of this class - i.e. a class with just static fields or methods.


This rule will generate an error if the class violates any of the following:

  • The class is not declared final as it cannot have subclasses
  • The class has a non private default constructor
  • The class has a non default constructor
  • The class has any instance methods or fields
  • The class has a field referencing itself - i.e. private static Class instance;
  • The class has a method who’s return type is that of the class
  • The class is annotated with Singleton as its mutually exclusive with NoInstance


uk.org.retep.annotations.Singleton


Action when violated: Compile time error

Mutually excludes: uk.org.retep.annotations.NoInstance


A class marked with Singleton implies that there is only a single instance of this class .


This rule will generate an error if the class violates any of the following:

  • The class is not declared final as it cannot have subclasses
  • The class has a non private default constructor
  • The class has a non default constructor
  • The class has no instance methods or fields
  • The class does not have a private static field referencing itself - i.e. private static Class instance;
  • The class does not have a public static method who’s return type is that of the class
  • The class is annotated with NoInstance as its mutually exclusive with Singleton


3 Miscellaneous


This set of rules are not associated with any annotations but enforce certain optional rules.


3.1 hashCode and Equals


When enabled ensures that if a class overrides either of the hashCode() or equals() methods then a compiler error is issued if the class does not override both of them. This is because there is a contract between those two methods where equals() can return true only if the hashCode of both object are also equal (read the docs for java.lang.Object if you disagree).


This rule came about because recently I had a class that was misbehaving in a map and it was because it had not defined both methods.


This rule is enabled by default and can be turned off by passing a configuration parameter to javac.


3.2 Missing javadoc comments


When enabled this rule will generate either a compiler warning or error if a non-private method has no documentation. This option is disabled by default but can be enabled by passing a configuration parameter to javac. The type of action when the rule is violated is itself configurable for this rule.


4 Configuration


The processor has some level of configurability, enabling certain rules to be enabled or disabled depending on user requirements.


4.1 Javac


When using the javac command you can pass any of the following options on the command line, prefixing them with -A. They then take a single value, either true or false to turn that option on or off. For example to turn on the missing javadoc rule, then you would pass -AwarnMissingJavadocs=true to javac.


4.2 Maven


When using the maven compiler plugin you are supposed to be able to add the javac options to the pom by using the compilerArgument attribute:


<compilerArgument>-AfailHashCodeEquals=true -AwarnMissingJavadocs=true</compilerArgument>


The problem is that although this is shown in the plugins documentation, it doesn’t work as it gets passed to javac as a single argument and not as a set of arguments.


To get around this the processor also supports a special option called mavenOpts who’s value is a comma separated list of the required features - if the feature is in the string then it is enabled. To disable a feature then simply prefix the feature with either ! or ^ - there’s two options to negate as some shells use ! so it’s not always possible to use on the command line:


<compilerArgument>-AmavenOpts=failHashCodeEquals,^warnMissingJavadocs</compilerArgument>


4.3 Currently supported options


failHashCodeEquals

Should an error occur if one of hashCode or equals is overridden but not the other? Enabled by default


warnMissingJavadocs

If enabled a compiler warning is generated for each non private method or field that has no documentation.


failMissingJavaDocs

This overrides warnMissingJavadocs if enabled. This will cause a compiler error to be issued if a non private method or field has no documentation.