Value Generator Plugin for Datanucleus HBase

As promised in my last blog post about HBase and Spring Roo I’ll show you now how to create your own Datanucleus plugin in order to support the @GeneratedValue annotation for HBase.

I’m using the following tools and versions:

  • Spring STS (Source Tool Suite) 2.5.0 RELEASE
  • hbase 0.89.20100924+28 (Cloudera CDH3 Beta)
  • hadoop 0.20.2+737 (Cloudera CDH3 Beta)
  • Datanucleus Core 2.2.1-release

Ok, so let’s get started:

  1. Create a Java project using Spring STS (or any other IDE)
  2. Create a Java class which implements the interface org.datanucleus.store.valuegenerator.ValueGenerator
    public class IncrementGenerator  implements ValueGenerator {
        private String name;
        private Properties properties;
        private String key;
        private HBaseAdmin admin;
        private HTable table;
        private long current = -1;
    
    	public IncrementGenerator(String name, Properties props)
    	{
    		this.name = name;
    		this.properties = props;
    		this.key = name;
    	}
    
    	public String getName() {
    		return this.name;
    	}
    
    	public Object next() {
    		return nextValue();
    	}
    
    	public void allocate(int additional) {
    		if(this.table == null) {
    			this.init();
    		}
    	}
    
    	public Object current() {
    		if(this.table == null) {
    			this.init();
    		}
    		return this.current();
    	}
    
    	public long nextValue() {
    		if(this.table == null) {
    			this.init();
    		}
    
    		try {
    			this.current = table.incrementColumnValue(Bytes.toBytes(key), Bytes.toBytes("sequence"), Bytes.toBytes("seq"), 1);
    		} catch (IOException ex) {
    			throw new NucleusDataStoreException("Error incrementing sequence.", ex);
    		}
    
    		return this.current;
    	}
    
    	public long currentValue() {
    		if(this.table == null) {
    			this.init();
    		}
    
    		if(this.current < 0 ) {
    			throw new NucleusDataStoreException();
    		}
    
    		return this.current;
    	}
    
    	private synchronized void init() {
    		if(this.table == null) {
    			try {
    				Configuration config = HBaseConfiguration.create();
    				this.admin = new HBaseAdmin( config );
    
    				if(!admin.tableExists("mySequenceTable")) {
    					HTableDescriptor ht = new HTableDescriptor( "mySequenceTable" );
    					HColumnDescriptor hcd = new HColumnDescriptor( "sequence" );
    					hcd.setCompressionType(Algorithm.NONE);
    					hcd.setMaxVersions(1);
    					ht.addFamily( hcd );
    					admin.createTable(ht);
    				}
    
    				this.table = new HTable(config, "mySequenceTable");
    				if(!this.table.exists(new Get(Bytes.toBytes(key)))) {
    					this.table.put(new Put(Bytes.toBytes(key)).add(Bytes.toBytes("sequence"), Bytes.toBytes("seq"), Bytes.toBytes(0l)));
    				}
    			}
    			catch(IOException ex) {
    				NucleusLogger.CONNECTION.fatal("Error instantiating IncrementGenerator", ex);
    			}
    		}
    	}
    }
    
  3. Create a file called plugin.xml with the following content
    Note: To create other value generators (i.e. sequence) check out the Datanucleus Value Generator documentation
    . I’ve chosen to use the increment value generator, because it seems to be the default generator if the generation type is set to Auto.
    <?xml version="1.0" encoding="UTF-8"?>
    <?eclipse version="3.4"?>
    <plugin>
    <!-- SEQUENCE GENERATOR -->
     <extension point="org.datanucleus.store_valuegenerator">
     <valuegenerator name="increment" class-name="org.peterrainer.datanucleus.hbase.valuegenerator.IncrementGenerator" unique="true"/>
    </extension>
    </plugin>
    
  4. Create a file called MANIFEST.MF in a folder called META-INF with the following content
    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: HBase GeneratedValue Increment Plugin-in
    Bundle-SymbolicName: org.peterrainer.datanucleus.hbase.valugenerator;singleton=true
    Bundle-Version: 1.0.0
    Bundle-Vendor: Peter Rainer
    
  5. Package all into a JAR file and load it into the build path of your HBase JPA application – so the following pice of code should work now
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

Note: This is an example and therefore has certain limitations in order to make it easier to understand – i.e. only one ValueGenerator can be used as the name argument is used as the key – the constructor gets passed the following arguments in case the ValueGenerator type is increment (so in a real world example you would probably use the field-name property as a key)

  • name = “increment”
  • Properties
    • field-name = “org.my.test.domain.Person.id”
    • root-class-name = “org.my.test.domain.Person”
    • class-name = “org.my.test.domain.Person”

If time permits I’ll try to enhance this example and publish it on GitHub, so it can easily be reused in other projects. In one of my next blog posts I’ll show you how to simplify Spring Roo projects even further by using this Datanucleus plugin.

As always any comments and/or feedback are welcome and I’m open for any ideas on how to do things better, easier and faster.

About these ads

One thought on “Value Generator Plugin for Datanucleus HBase

  1. Pingback: Value Generator Plugin for Datanucleus HBase will become part of Datanucleus 3 « Peter Rainer's Weblog

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