TP Enhancement On Java

This topic applies to Java version only 

TP Enhancement on Java platform can be done by customizing the ant build script to include instrumentation for persistent classes. 

For a simple example we will use SensorPanel class, which represents a simple linked list. In our example application we will first store several objects of this class, then retrieve and modify them. Transparent Persistence mechanism should take care of modified objects and persist them to the database when the transaction is committed or the database is closed. As SensorPanel does not implement Activatable interface, we will need to use db4o enhancement tools to implement this interface after the class is built.

Let's look at our example code.

First, we need to configure Transparent Persistence:

TPExample.java: configureTP
1private static Configuration configureTP() { 2 Configuration configuration = Db4o.newConfiguration(); 3 // add TP support 4 configuration.add(new TransparentPersistenceSupport()); 5 return configuration; 6 }
 

Now we will store a linked list of 10 elements: 

TPExample.java: storeSensorPanel
01private static void storeSensorPanel() { 02 new File(DB4O_FILE_NAME).delete(); 03 ObjectContainer container = database(Db4o.newConfiguration()); 04 if (container != null) { 05 try { 06 // create a linked list with length 10 07 SensorPanel list = new SensorPanel().createList(10); 08 container.store(list); 09 } finally { 10 closeDatabase(); 11 } 12 } 13 }

And the following procedure will test the effect of TP:

TPExample.java: testTransparentPersistence
01private static void testTransparentPersistence() { 02 storeSensorPanel(); 03 Configuration configuration = configureTP(); 04 05 ObjectContainer container = database(configuration); 06 if (container != null) { 07 try { 08 ObjectSet result = container.queryByExample(new SensorPanel(1)); 09 listResult(result); 10 SensorPanel sensor = null; 11 if (result.size() > 0) { 12 System.out.println("Before modification: "); 13 sensor = (SensorPanel) result.get(0); 14 // the object is a linked list, so each call to next() 15 // will need to activate a new object 16 SensorPanel next = sensor.getNext(); 17 while (next != null) { 18 System.out.println(next); 19 // modify the next sensor 20 next.setSensor(new Integer(10 + (Integer)next.getSensor())); 21 next = next.getNext(); 22 } 23 // Explicit commit stores and commits the changes at any time 24 container.commit(); 25 } 26 } finally { 27 // If there are unsaved changes to activatable objects, they 28 // will be implicitly saved and committed when the database 29 // is closed 30 closeDatabase(); 31 } 32 } 33 // reopen the database and check the modifications 34 container = database(configuration); 35 if (container != null) { 36 try { 37 ObjectSet result = container.queryByExample(new SensorPanel(1)); 38 listResult(result); 39 SensorPanel sensor = null; 40 if (result.size() > 0) { 41 System.out.println("After modification: "); 42 sensor = (SensorPanel) result.get(0); 43 SensorPanel next = sensor.getNext(); 44 while (next != null) { 45 System.out.println(next); 46 next = next.getNext(); 47 } 48 } 49 } finally { 50 closeDatabase(); 51 } 52 } 53 }

Of course, if you will run the code above as is, you will see that all the changes were lost. In order to fix it we will need to build the application with a special build script:

Build.Xml
01<?xml version="1.0"?> 02 03<!-- 04 TP build time enhancement sample. 05--> 06 07<project name="tpexamples" default="buildall"> 08 09 <!-- 10 Set up the required class path for the enhancement task. 11--> 12 <path id="db4o.enhance.path"> 13 <pathelement path="${basedir}" /> 14 <fileset dir="lib"> 15 <include name="**/*.jar" /> 16 </fileset> 17 </path> 18 19 <!-- Define enhancement task. --> 20 <taskdef name="db4o-enhance" classname="com.db4o.instrumentation.ant.Db4oFileEnhancerAntTask" classpathref="db4o.enhance.path" loaderref="db4o.enhance.loader" /> 21 22 <typedef name="transparent-persistence" classname="com.db4o.ta.instrumentation.ant.TAAntClassEditFactory" classpathref="db4o.enhance.path" loaderref="db4o.enhance.loader" /> 23 24 25 26 <target name="buildall" depends="compile"> 27 28 <!-- Create enhanced output directory--> 29 <mkdir dir="${basedir}/enhanced-bin" /> 30 <delete dir="${basedir}/enhanced-bin" quiet="true"> 31 <include name="**/*" /> 32 </delete> 33 34 <db4o-enhance classtargetdir="${basedir}/enhanced-bin"> 35 36 <classpath refid="db4o.enhance.path" /> 37 <!-- Use compiled classes as an input --> 38 <sources dir="${basedir}/bin" /> 39 40 <!-- Call transparent persistence enhancement --> 41 <transparent-persistence /> 42 43 </db4o-enhance> 44 45 </target> 46 47 <!-- Simple compilation. Note that db4o version 48 should be adjusted to correspond to the version 49 you are using 50 --> 51 <target name="compile"> 52 <javac fork="true" destdir="${basedir}/bin"> 53 <classpath> 54 <pathelement location="${basedir}/lib/db4o-7.1.26.8872-java5.jar" /> 55 </classpath> 56 <src path="${basedir}/src" /> 57 <include name="**/*.java" /> 58 </javac> 59 </target> 60 61</project>

The build script relies on several jars:

All these jars should be added to /lib folder in the project directory.

After running the build script above you will get /bin and /enhanced-bin folders produced in your project folder. /bin folder contains compiled application classes, whereas /enhanced-bin contains compiled and enhanced classes. For testing the result of the enhancement you can use the following batch file (to be run from /enhanced-bin folder):

set CLASSPATH=.;{$PROJECT_ROOT}\lib\db4o-x.x-java5.jar

java com.db4odoc.tpbuildtime.TPExample