SimpleStore Developers Guide

Table of Contents

 

About this Guide

This guide is intended for service providers. This document describes core interfaces and can be useful for SimpleStore users and Bean providers too.

Introduction

SimpleStore is a Java-based persistence framework, a simple and powerful abstraction for transactional storage. This guide is an overview of the transactional storage basics, focuses on the main area for SimpleStore extentions: custom Storge and TransactionManager implementations.

Context

Context is factory for service implementation, you can provide any interface implementation returned by this factory.

 /** Creates new ContextImpl */
    public ContextImpl( MetaClass metaClass,TypeConverter typeConverter,
          OIDGenerator  generator, Storage storage,
          Cache cache,TransactionManager transactionManager  ) {
        metaClass.setContext( this );
        storage.setContext( this );
        this.generator = generator;
        this.metaClass = metaClass;
        this.storage = storage;
        this.cache = cache;
        this.transactionManager = transactionManager;
        this.typeConverter = typeConverter;
    }
 

PersitenceManagerFactory

This factory is used to setup PersistenceManager and Context. PersistenceManager getPersistenceManager() must return singleton menger instanse.

  MetaClassImpl.parse(loader.getResourceAsStream( metaResource),loader);
                
                MetaClassImpl mclass = new MetaClassImpl( MetaClassImpl.class.getClassLoader());
                RecordManager recman = new RecordManager( file );
                ObjectCache cache = new ObjectCache( recman, new MRU( 100 ) );
                JDBMStorage storage = new JDBMStorage(recman ,cache,new LongComparator());
                ContextImpl context = new ContextImpl(
                mclass, new DefaultTypeConverter(),
                new RandomOIDGenerator(),
                storage,
                SoftRefMemoryCache.getInstance(new java.util.HashMap(),maxStrongRef),
                storage );
                pm = PersistenceManagerImpl.getPersistenceManager(context);

PersitenceManager

It is a high level interface it doe's not depend on Storage. Default implementation can be used for any Storage implementation. It is fragment from PersitenceManager implementation.

  public Object createInstance( Class aclass ) {
       
        Persistent p = context.getMetaClass(aclass).newInstance();
        context.getCache().put( p.getOID(), p );
        return p;
    }

    public Object findInstance( Class clasz, Object oid ) throws StorageException {
        return context.getStorage().retrieveObject( clasz, oid );
    }
 

TransactionManager

It has single method InternalTransaction getTransaction(). In some cases this interface is implemented by Storage. Extend AbstratStorage if your transactions are managed by Storage. Both storage types distributed with SimleStore use Storage managed transactions. You will need to imlement Transaction manager, if your transactions are distributed. JTA is recommended API for distributed transactions.

Storage

You must implement all Storage methods, if you decided to use custom Storage implementation. It is trivial interface for main Storage operations like create, find, remove and update. Implementation must use Cache for reachability management and Identity. Single persistent object instance must be loaded with the same OID. OID object and persistent's class is unique pair. Use storege implementations as examples or base classes for custom storage implementations.

public java.util.Collection retrieve(Class clasz, int index, Object value)
                                                        throws StorageException{
        
        final Set objects = new HashSet();
        final MetaClass mClass =  context.getMetaClass(clasz);
        final String sql = "SELECT "+ mClass.getOIDName() + " AS " + INTERNAL_OID +
                              ", * FROM " + mClass.getName() +
        " WHERE " + mClass.getPropertyName(index) + "=?";
        //find uncommited objects first
        java.util.Collection tObjects = context.getTransactionManager().getTransaction().getTransactionalObjects();
        for( java.util.Iterator i = tObjects.iterator(); i.hasNext(); ){
          MetaObject mo = (MetaObject)i.next();
           if( mo.getPersistentClass().equals(clasz) ){
           if( (value == null) && (mo.getProperty(index) == null) ){  
                    objects.add( mo.getObject() );
                    continue;
                  }
                 if( value != null && value.equals(mo.getProperty(index))  ){
                    objects.add( mo.getObject() );
                    continue;
                 }
           } 
        }
       //execute SQL statement
        excecute( sql, new Object[]{value}, new QueryHandler(objects, clasz));
        
        return objects;
    }
 

Cache

It is recommended to use default SoftMemoryCache implementation, but you can use any implementation. Cache has no method to remove mapping. Simplestore can return deleted in Storage object from Cache. Managed methods throw IllegalStateExeption if object is deleted, use PersistenceManager::isDeleted(Object obj) to test object returned from Cache.

MetaClass

MetaClass describes persistent fields and it is factory for persistent insatnces. You can implement MetaClass to change default DTD for metadata, store it in some custom format or database.

Enhancment

SimleStore provides utility for Class enhancement. It used to implement persistence, but you can use it for any aspect like logging, authorization or generate dynamic Proxy for distributed objects, Object to XML mapping. SimpleStore use BCEL to enhance classes and implement Persistent interface. Generated code for java.util.Vector:

public boolean removeElement(Object arg1)
Code(max_stack = 8, max_locals = 8, code_length = 112)

0: iconst_1 1: anewarray <java.lang.Object> (16) 4: dup 5: iconst_0 6: aload_1 7: aastore 8: astore_2 9: aload_0 10: getfield org.apache.java.util.Vector$$EnhancedBySimplestore$$.h Lorg/apache/commons/simplestore/tools/MethodInterceptor; (14) 13: aload_0 14: getstatic org.apache.java.util.Vector$$EnhancedBySimplestore$$.METHOD_23 Ljava/lang/reflect/Method; (240) 17: aload_2 18: invokeinterface org.apache.commons.simplestore.tools.MethodInterceptor.beforeInvoke (Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object; (49) 4 0 23: astore_3 24: aconst_null 25: astore %4 27: iconst_0 28: istore %5 30: aconst_null 31: astore %6 33: aload_0 34: getfield org.apache.java.util.Vector$$EnhancedBySimplestore$$.h Lorg/apache/commons/simplestore/tools/MethodInterceptor; (14) 37: aload_0 38: getstatic org.apache.java.util.Vector$$EnhancedBySimplestore$$.METHOD_23 Ljava/lang/reflect/Method; (240) 41: aload_2 42: aload_3 43: invokeinterface org.apache.commons.simplestore.tools.MethodInterceptor.invokeSuper (Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Ljava/lang/Object;)Z (57) 5 0 48: ifeq #73 51: iconst_1 52: istore %5 54: new <java.lang.Boolean> (63) 57: dup 58: aload_0 59: aload_1 60: invokespecial java.util.Vector.removeElement (Ljava/lang/Object;)Z (243) 63: invokespecial java.lang.Boolean.<init> (Z)V (70) 66: astore %4 68: goto #73 71: astore %6 73: aload_0 74: getfield org.apache.java.util.Vector$$EnhancedBySimplestore$$.h Lorg/apache/commons/simplestore/tools/MethodInterceptor; (14) 77: aload_0 78: getstatic org.apache.java.util.Vector$$EnhancedBySimplestore$$.METHOD_23 Ljava/lang/reflect/Method; (240) 81: aload_2 82: aload_3 83: iload %5 85: aload %4 87: aload %6 89: invokeinterface org.apache.commons.simplestore.tools.MethodInterceptor.afterReturn (Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Ljava/lang/Object;ZLjava/lang/Object;Ljava/lang/Throwable;)Ljava/lang/Object; (53) 8 0 94: astore %7 96: aload %7 98: ifnonnull #103 101: iconst_0 102: ireturn 103: aload %7 105: checkcast <java.lang.Boolean> (63) 108: invokevirtual java.lang.Boolean.booleanValue ()Z (74) 111: ireturn
Exception handler(s) = From To Handler Type 54 68 71 java.lang.Throwable(76)
Decompiled code:

 package  org.apache.java.util;

 public class  Vector$$EnhancedBySimplestore$$  extends java.util.Vector{

 org.apache.commons.simplestore.tools.MethodInterceptor h;
 //...
 static java.lang.reflect.Method  METHOD_23 =
                Vector.class.getMethod("removeElement",
                                           new Class[]{Object.class}
                                   ); 
 //...

 public boolean removeElement(Object arg1){

   Object args[] = { arg1 };
   Object retValFromBefore = h.beforeInvoke(this,METHOD_23,args);
   boolean invokedSuper = false;
   Throwable t = null;
   Object retValFromSuper = null;

   if( h.invokeSuper(this,METHOD_23,args,retValFromBefore) ){
     invokedSuper = true;
   try{

      retValFromSuper = new Boolean( super.removeElement(arg1) );

    }catch(Throwable tl){
        t = tl
    }

   }

  return ((Boolean) h.afterReturn(this, METHOD_23, args,
                       retValFromBefore, invokedSuper, retValFromSuper,t )
            ).booleanValue();

}
This code will not compile it doe's not handle Throwable.

Persistent

This interface is implemented by enhancer. PersistentProxy returns this implementation.

Proxy

PersistentProxy impements MethodInterceptor for generated Persistent class. It implements methods to handle persistent object Identity and State.

State

MetaObject manages persistent object state. Persistent returns this implementation. This interface is used by Storage implementation too.

public interface MetaObject extends Cloneable {

    public Object getOID();

    public Object  getProperty(int index);

    public void  setProperty(int index, Object value);

    public Object[]  getProperties();

    public Class  getPersistentClass();

    public boolean  isDirty();

    public boolean  isNew();

    public boolean  isDeleted();
    
    public boolean  isClean();

    public void  remove();

    public boolean  isLoaded();

    public void  setDirty(boolean dirty);

    public Persistent  getObject();
    
    public Object  clone()throws CloneNotSupportedException;
    
    public void  assign( MetaObject mo);
    
    public MetaClass  getMetaClass();
    
}

Identity

Implement OIDGenerator interface for custom OID generation. Default implementation returns random number. Returned object must be unique, it is used as key in Cache and as identity in Storage.

    PersistenceManager.getOID(object1).
                    equals(PersistenceManager.getOID(object2) );
     

<==>

object1 == object2;

<==>

object1.equals(object2);

Validation

Metadata is used to map Validator and field. NotNull validator can be used as example. Persistent throws ValidationException for write methods if isValid() return false, this Exception contains all information for invalid property value.

Interceptors

Interceptor calls Context before invoking any public or protected method on persistent object. onInvoke can be used for security checks or validation. Any Runtime exeption aborts method execution. public void onInvoke(java.lang.Object object, java.lang.reflect.Method method, Object[] args);


Copyright © 1999-2002, Apache Software Foundation