You are here: Advanced Features > Type Handling > Typehandlers > Custom Typehandler Example

Custom Typehandler Example

For a custom typehandler example we will try to write a very simple typehandler for the StringBuilder class. We want to handle a StringBuilder as a value type, therefore we implement the ValueTypeHandler interface. Not that there's a whole collection of interfaces for typehandlers. Take a look at the TypeHandler4 type hierarchy.

To keep it simple we will skip information required for indexing - please look at IndexableTypeHandler in db4o sources to get more information on how to handle indexes.

The first thing should be the write method, which determines how the object is persisted:

@Override
public void write(WriteContext writeContext, Object o) {
    StringBuilder builder = (StringBuilder) o;
    String str = builder.toString();
    final byte[] bytes = str.getBytes(CHAR_SET);
    writeContext.writeInt(bytes.length);
    writeContext.writeBytes(bytes);
}
StringBuilderHandler.java: Write the StringBuilder

As you can see from the code above, there are 3 steps:

  1. Get the buffer from WriteContext/I WriteContext
  2. Convert the string-content to a byte-array using the UTF8 encoding.
  3. Write the length of the resulted byte-array.
  4. Write the byte array of the string.

Next step is to read the stored object. It is just opposite to the write method:

@Override
    public Object read(ReadContext readContext) {
        final int length = readContext.readInt();
        byte[] data = new byte[length];
        readContext.readBytes(data);
        return new StringBuilder(new String(data,CHAR_SET));
    }
}
StringBuilderHandler.java: Read the StringBuilder

Delete is simple - we just reposition the buffer offset to the end of the slot:

@Override
public void delete(DeleteContext deleteContext) throws Db4oIOException {
    skipData(deleteContext);
}

private void skipData(ReadBuffer deleteContext) {
    int numBytes = deleteContext.readInt();
    deleteContext.seek(deleteContext.offset()+ numBytes);
}
StringBuilderHandler.java: Delete the content

The last method left: #defragment. This one only moves the offset to the beginning of the object data, i.e. skips Id and size information (to be compatible to older versions):

@Override
public void defragment(DefragmentContext defragmentContext) {
    skipData(defragmentContext);
}
StringBuilderHandler.java: Defragment the content

Now to use this type handler we need to configure db4o. To register a typehandler you have to provide a predicate which decides if a type is handled by the typehandler and the typehandler itself.

EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
configuration.common().registerTypeHandler(
        new SingleClassTypeHandlerPredicate(StringBuilder.class), new StringBuilderHandler());
TypeHandlerExample.java: Register type handler

After that all string builders are handled by you're type handler.