![]() |
This guide is intended for service providers. This document describes core interfaces and can be useful for SimpleStore users and Bean providers too.
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 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; }
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);
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 ); }
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.
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; }
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
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.
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)Decompiled code:
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)
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
.
This interface is implemented by enhancer.
PersistentProxy
returns this implementation.
PersistentProxy
impements MethodInterceptor
for
generated Persistent class. It implements methods
to handle persistent object Identity and 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(); }
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);
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.
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);