16. Enhancement


As we have seen both Transparent Activation and Native Queries will produce correct results out-of-the-box.

To get your application to run as fast as possible with db4o, you will want to make sure that only required objects are loaded from the database and that Native Queries are optimized to use field indexes where this is possible.

Theoretically you could write all the necessary code by hand but you will save yourself a lot of time if you use automatic enhancement.

The db4o enhancer tools will add code to your persistent classes to make them work even better with db4o.

db4o for Java supplies three different enhancer strategies:
Enhancing at Compile/Deployment Time
Enhancing at Class Loading Time
Native Query Optimization at Query Execution Time


    16.1. Required Libraries


    The enhancer tasks require the addition of the following libraries to your project:

    ant.jar  
    for using the Ant enhancer task

    bloat-1.0.jar
    the bytecode optimization library

    db4o-7.0-instrumentation.jar
    instrumentation library on top of bloat

    db4o-7.0-java5.jar
    the db4o core engine

    db4o-7.0-nqopt.jar
    the Native Query Optimizer

    db4o-7.0-taj.jar
    the Transparent Activation Framework for Java

    db4o-7.0-tools.jar
    the tools interface that provides the top level enhancer tasks.



    16.2. Enhancing at Compile Time


    The db4o enhancer adds code to class files or jar files. Afterwards these files will be slightly different to what the debugger expects.

    In the setup the db4o team has been working with, using the Eclipse IDE, enhancing has worked perfectly when files were instrumented in-place, directly in the /bin/ directory where the Eclipse compiler places compiled class files. In all our tests the Eclipse debugger simply ignored additional statements and stepped over them and debugging worked perfectly as usual.

    The db4o enhancer technology is new. Not all possible development environment setups have been checked by the db4o team and there may be incompatibility issues with your IDE when enhancing class and library files in place. By trying out in-place enhancement with your setup and by reporting back issues to the db4o forums you can help the db4o team to improve enhancement for your personal setup. A possible strategy to resolve problems with in-place enhancement would be to use different output directories than /bin and /lib as output paths for the enhancer and to run your enhanced application from there.  


      16.2.1. Enhancing with Ant


      db4otools.jar contains the main enhancer task:
      com.db4o.enhance.Db4oEnhancerAntTask

      For all possibilities of using this task see the  topic on build time enhancement in the reference documentation.

      The simplest enhancer task does both: It optimizes Native Queries and it adds the Activatable interface to your classes, making sure a persistent object is activated whenever any field is read.

      Here is an example of how an Ant script could look like. This script enhances all class files and jar files except for the db4o libraries in-place, in the /bin and /lib directory of your project:

      <?xml version="1.0"?>
      <project name="db4o enhance project" default="enhance" basedir=".">
          
          <path id="project.classpath">
              <pathelement path="${basedir}/bin" />
              <fileset dir="lib">
                  <include name="**/*.jar"/>
              </fileset>
          </path>
          
          <taskdef name="db4o-enhance"
              classname="com.db4o.enhance.Db4oEnhancerAntTask"
              classpathref="project.classpath" />
          
          <target name="enhance">
              <db4o-enhance classtargetdir="${basedir}/bin" jartargetdir="${basedir}/lib">
                  <classpath refid="project.classpath" />        
                  <sources dir="${basedir}/bin" />
                  <jars dir="${basedir}/lib">
                      <include name="*.jar" />
                      <exclude name="db4o-*.jar" />
                      <exclude name="ant.jar" />
                      <exclude name="bloat-1.0.jar" />
                  </jars>
              </db4o-enhance>
          </target>
          
      </project>


      If you use Eclipse, there is a very convenient way to make sure an Ant script is executed every time after compilation and before you run your application: You can add a builder to your project. To do this, right click on your project, choose "Properties" + "Builders" + "New" + "Ant Builder" and enter the name of the build file you created.


      16.2.2. Programmatic Enhancement


      The db4o enhancer is just another Java application so of course you can start it directly. The enhancer user interface is a convenience interface to the underlying instrumentation layer. To take advantage of all the possibilities you may want to consider a look at the sources of com.db4o.instrumentation.main.Db4oFileInstrumentor and call instrumentation directly.

      Here is a very basic example how you could enhance all the files in the /bin folder below the project 'myproject' using the Db4oFileEnhancer:

      import com.db4o.enhance.*;

      public static void main(String[] args) throws Exception {
          String path = "../myproject/bin";
          new Db4oFileEnhancer().enhance(path, path);
      }




    16.3. Enhancing at Load Time


    As an alternative to enhancing classes at build time, it is also possible to run a db4o application using a special launcher. Under the hood the Db4oEnhancedLauncher installs a special ClassLoader that instruments classes for db4o on the fly, when they are loaded.

    For using the launcher, please see the method signatures of
    Db4oEnhancedLauncher#launch()





    16.4. NQ Optimization at Querying Time


    In case no other enhancer has been run previously, Native Queries will still be optimized automatically if the following optimization libraries are found in the CLASSPATH:
    bloat-1.0.jar, db4o-7.0-classedit.jar, db4o-7.0-nqopt.jar

    The Native Query optimizer is still under development to eventually "understand" all Java constructs. Current optimization supports the following constructs well:

    - compile-time constants
    - simple member access
    - primitive comparisons
    - #equals() on primitive wrappers and Strings
    - #contains()/#startsWith()/#endsWith() for Strings
    - arithmetic expressions
    - boolean expressions
    - static field access
    - array access for static/predicate fields
    - arbitrary method calls on static/predicate fields (without candidate based params)
    - candidate methods composed of the above
    - chained combinations of the above

    Note that the current implementation does not support polymorphism and multiline methods yet.


    16.5. Monitoring Native Query optimization


    To find out if a Native Query runs optimized or unoptimized you can attach a query execution listener as follows:

    ((ObjectContainerBase)db).getNativeQueryHandler().addListener(new Db4oQueryExecutionListener() {
      public void notifyQueryExecuted(NQOptimizationInfo info) {
        System.err.println(info);
      }
    });


    The listener will be notified on each native query call and will be passed the Predicate object processed, the optimized expression tree (if successful) and the success status of the optimization run:

    NativeQueryHandler.UNOPTIMIZED ("UNOPTIMIZED")
      if the predicate could not be optimized and is run in unoptimized mode

    NativeQueryHandler.PREOPTIMIZED ("PREOPTIMIZED")
      if the predicate already was optimized (due to class file or load time
      instrumentation)

    NativeQueryHandler.DYNOPTIMIZED ("DYNOPTIMIZED")
      if the predicate was optimized at query execution time



    www.db4o.com