JPOX
JPOX
 Project  |  Ver 1.1  |  Ver 1.2  |  JDO  |  JPA  |  Guides  |  Tools
1.2 | Persistence | JDO ORM | JPA ORM | Runtime | JDO Runtime | JPA Runtime | Extensions | Developer
JPOX Runtime
RDBMS Datastores
DB4O Datastore
JPOX Enhancer

As is described in the ByteCode Enhancement guide, JPOX utilises the common technique of byte-code manipulation to make your normal Java classes "persistable". The mechanism provided by JPOX is to use an "enhancer" process to perform this manipulation before you use your classes at runtime. The process is very quick and easy.

How to use the JPOX Enhancer depends on what environment you are using. Below are some typical examples.

Manually

JPOX provides a JAR containing the Enhancer (jpox-enhancer.jar). If you are building your application manually and want to enhance your classes you follow the instructions in this section. You invoke the enhancer as follows

java -cp classpath  org.jpox.enhancer.JPOXEnhancer [options] [jdo-files] [class-files]
    where options can be
        -persistenceUnit persistence-unit-name : Name of a "persistence-unit" to enhance the classes for
        -d target-dir-name : Write the enhanced classes to the specified directory
        -api api-name : Name of the API we are enhancing for (JDO, JPA). Default is JDO
        -enhancerName name : Name of the ClassEnhancer to use. Options BCEL, ASM
        -checkonly : Just check the classes for enhancement status
        -v : verbose output

    where classpath must contain the following
        jpox-enhancer.jar
        jpox-core.jar
        bcel.jar (or asm.jar if using ASM)
        jdo2-api.jar
        log4j.jar (optional)
        your classes
        your meta-data files

The input to the enhancer should be either a set of MetaData/class files or the name of the "persistence-unit" to enhance. In the first option, if any classes have annotations then they must be specified. All classes and MetaData files should be in the CLASSPATH when enhancing. To give an example of how you would invoke the enhancer

Linux/Unix :
java -cp target/classes:lib/jpox-enhancer.jar:lib/jpox-core.jar:lib/jdo2-api.jar:lib/log4j.jar:lib/bcel.jar
     -Dlog4j.configuration=file:log4j.properties
     org.jpox.enhancer.JPOXEnhancer 
     **/*.jdo

Windows :
java -cp target\classes;lib\jpox-enhancer.jar;lib\jpox-core.jar;lib\jdo2-api.jar;lib\log4j.jar;lib\bcel.jar
     -Dlog4j.configuration=file:log4j.properties
     org.jpox.enhancer.JPOXEnhancer -v
     target/classes/org/jpox/examples/inverse/package.jdo
     target/classes/org/jpox/examples/normal/package.jdo

[should all be on same line. Shown like this for clarity]

So you pass in your JDO MetaData files (and/or the class files wihich use annotations) as the final argument(s) in the list, and include the respective JAR's in the classpath (-cp). The enhancer responds as follows

JPOX Enhancer (version 1.1.0) : Enhancement of classes

JPOX Enhancer : Classpath
>>  /home/andy/work/JPOX/samples/packofcards/target/classes
>>  /home/andy/work/JPOX/samples/packofcards/lib/log4j.jar
>>  /home/andy/work/JPOX/samples/packofcards/lib/jdo2-api.jar
>>  /home/andy/work/JPOX/samples/packofcards/lib/jpox-core.jar
>>  /home/andy/work/JPOX/samples/packofcards/lib/jpox-enhancer.jar
>>  /home/andy/work/JPOX/samples/packofcards/lib/bcel.jar

JPOX Enhancer : Using ClassEnhancer "bcel" for API "JDO"

JPOX Enhancer : Input Files
>>  /home/andy/work/JPOX/samples/packofcards/target/classes/org/jpox/examples/inverse/package.jdo
>>  /home/andy/work/JPOX/samples/packofcards/target/classes/org/jpox/examples/normal/package.jdo

Processing class "org.jpox.examples.inverse.Pack"
ENHANCED: org.jpox.examples.inverse.Pack
Processing class "org.jpox.examples.inverse.Card"
ENHANCED: org.jpox.examples.inverse.Card
Processing class "org.jpox.examples.normal.Pack"
ENHANCED: org.jpox.examples.normal.Pack
Processing class "org.jpox.examples.normal.Card"
ENHANCED: org.jpox.examples.normal.Card
JPOX Enhancer completed with success for 9 classes. Timings : input=422 ms, enhance=490 ms, total=912 ms.
     ... Consult the log for full details

If you have errors here relating to "Log4J" then you must fix these first. If you receive no output about which class was ENHANCED then you should look in the JPOX enhancer log for errors. The enhancer performs much error checking on the validity of the passed MetaData and the majority of errors are caught at this point. You can also use the JPOX Enhancer to check whether classes are enhanced. To invoke the enhancer in this mode you specify the checkonly flag. This will return a list of the classes, stating whether each class is enhanced for persistence under JDO or not. The classes need to be in the CLASSPATH (Please note that a CLASSPATH should contain a set of JAR's, and a set of directories. It should NOT explictly include class files, and should NOT include parts of the package names. If in doubt please consult a Java book).



Maven1

Maven1 operates from a series of plugins. There is a JPOX plugin for Maven1 that allows enhancement of classes. Go to the Download section of the website and download this. Once you have the Maven1 plugin, you then need to set the properties for the plugin in your project.properties file. This will typically not require any addition to your project.properties. If you do need to change this file, the following parameters are the likely ones to change

maven.jpox.jdo.fileset.dir=${maven.build.dest}  # Location of the JDO files
maven.jpox.jdo.fileset.include=**/*.jdo         # fileset to include
#maven.jpox.jdo.fileset.exclude=something.jdo   # fileset to exclude, if any

maven.jpox.classes.dir=${maven.build.dest}      # Location of classes to enhance
maven.jpox.api=JDO                              # API to enhance to (JDO, JPA)
maven.jpox.enhancer.classenhancer=bcel          # Use BCEL

maven.jpox.inputmode=files                      # Mode of input. Can also be set to "persistenceunit"
maven.jpox.persistenceunit=                     # Name of the persistence-unit to enhance
maven.jpox.log4j.configuration=                 # Log definition to use
maven.jpox.verbose=true                         # Turn on more output ?

You then run the Maven JPOX plugin, as follows

maven jpox:enhance

This will enhance all classes found that correspond to the classes defined in the JDO files in your source tree. If you want to check the current status of enhancement you can also type

maven jpox:enhance-check


Maven2

Maven2 operates from a series of plugins. There is a JPOX plugin for Maven2 that allows enhancement of classes. Go to the Download section of the website and download this. Once you have the Maven1 plugin, you then need to set the properties for the plugin in your project.properties file. This will typically not require any addition to your pom.xml. If you do need to change this file, the following parameters are the likely ones to change

Configuration name   Default Value     Description
mappingIncludes      **/*.jdo          Fileset to include
mappingExcludes                        Fileset to exclude, if any
log4jConfiguration   {internal props}  Log definition to use
persistenceUnitName                    Name of persistence-unit to enhance
enhancerName         ASM               Class Enhancer to use (ASM, BCEL)
api                  JDO               API to enhance to
verbose              false             Turn on more output ?

You then run the Maven2 JPOX plugin, as follows

mvn jpox:enhance

This will enhance all classes found that correspond to the classes defined in the JDO files in your source tree. If you want to check the current status of enhancement you can also type

mvn jpox:enhance-check

Or alternatively, you could add the following to your POM

    <build>
        ...
        <plugins>
            <plugin>
                <groupId>jpox</groupId>
                <artifactId>jpox-maven-plugin</artifactId>
                <version>1.2.0-beta-2</version>
                <configuration>
                    <log4jConfiguration>${basedir}/log4j.properties</log4jConfiguration>
                    <verbose>true</verbose>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        ...
    </build>

So you then get auto-enhancement after each compile



Ant

Ant provides a powerful framework for performing tasks. JPOX provides an Ant task to enhance classes. JPOX provides a JAR containing the Enhancer (jpox-enhancer.jar). You need to make sure that the jpox-enhancer.jar, jpox-core.jar, bcel.jar, log4j.jar and jdo2-api.jar are in your classpath. In the JPOX Enhancer Ant task, the following parameters are available

ParameterDescriptionvalues
dirOptional. Directory containing the JDO files to use for enhancing. Uses ant build file directory if the parameter is not specified.
destinationOptional. Defining a directory where enhanced classes will be written. If omitted, the original classes are updated.
apiOptional. Defines the API to be used when enhancingJDO, JPA
enhancerNameOptional. Defines the ClassEnhancer to use when enhancing. BCEL is the default up to and including 1.2.0-beta-4ASM | BCEL
persistenceUnitOptional. Defines the "persistence-unit" to enhance.
checkonlyWhether to just check the classes for enhancement status. Will respond for each class with "ENHANCED" or "NOT ENHANCED". This will disable the enhancement process and just perform these checks.true, false
verboseWhether to have verbose output.true, false
filesuffixesOptional. Suffixes to accept for the input files. The Enhancer Ant Task will scan for the files having these suffixes under the directory specified by dir option. The value can include comma-separated list of suffixes. If using annotations you can have "class" included as a valid suffix here or use the fileset.jdo
filesetOptional. Defines the files to accept as the input files. Fileset enables finer control to which classes / metadata files are accepted to enhanced. If one or more files are found in the fileset, the Enhancer Ant Task will not scan for additional files defined by the option filesuffixes. For more information on defining a fileset, see Apache FileSet Manual.
ifOptional. The name of a property that must be set in order to the Enhancer Ant Task to execute.

So you could define something like the following, setting up the parameters enhancer.classpath, jdo.file.dir, and log4j.config.file to suit your situation (the jdo.file.dir is a directory containing the JDO files defining the classes to be enhanced). The classes specified by the XML Meta-Data files, together with the XML Meta-Data files must be in the CLASSPATH (Please note that a CLASSPATH should contain a set of JAR's, and a set of directories. It should NOT explictly include class files, and should NOT include parts of the package names. If in doubt please consult a Java book).

<target name="enhance" description="JPOX enhancement">
    <taskdef name="jpoxenhancer" classpathref="enhancer.classpath" 
                classname="org.jpox.enhancer.tools.EnhancerTask" />

    <jpoxenhancer classpathref="enhancer.classpath"
        dir="${jdo.file.dir}" failonerror="true" verbose="true">
        <jvmarg line="-Dlog4j.configuration=${log4j.config.file}"/>
    </jpoxenhancer>
</target>

You can also define the files to be enhanced using a fileset. When a fileset is defined, the Enhancer Ant Task will not scan for additional files, and the option filesuffixes is ignored.

<target name="enhance" description="JPOX enhancement">
    <taskdef name="jpoxenhancer" classpathref="enhancer.classpath" 
                classname="org.jpox.enhancer.tools.EnhancerTask" />

    <jpoxenhancer
        dir="${jdo.file.dir}" failonerror="true" verbose="true">
        <fileset dir="${classes.dir}">
            <include name="**/*.jdo"/>
            <include name="**/acme/annotated/persistentclasses/*.class"/>
        </fileset>
        <classpath>
            <path refid="enhancer.classpath"/>
        </classpath>
    </jpoxenhancer>
</target>

You can disable the enhancement execution upon the existence of a property with the usage of the if parameter.

<target name="enhance" description="JPOX enhancement">
    <taskdef name="jpoxenhancer" classpathref="enhancer.classpath" 
                classname="org.jpox.enhancer.tools.EnhancerTask" if="aPropertyName"/>

    <jpoxenhancer classpathref="enhancer.classpath"
        dir="${jdo.file.dir}" failonerror="true" verbose="true">
        <jvmarg line="-Dlog4j.configuration=${log4j.config.file}"/>
    </jpoxenhancer>
</target>
Runtime Enhancement

Enhancement of persistent classes at runtime is possible when using JRE 1.5 or superior versions. Runtime Enhancement requires the following runtime dependencies: BCEL or ASM, JPOX Core and JPOX Enhancer libraries. To enable runtime enhancement, the javaagent option must be set in the java command line. Example:

java -javaagent:jpox-enhancer-1.2-SNAPSHOT.jar Main
                


Programmatic API

You could alternatively programmatively enhance classes from within your application. This is done as follows

import org.jpox.enhancer.JPOXEnhancer;

...
JPOXEnhancer enhancer = new JPOXEnhancer();
enhancer.setApi("JDO");
enhancer.setVerbose(true);
enhancer.setPersistenceUnitName("MyPersistenceUnit");
enhancer.execute();

This will look in META-INF/persistence.xml and enhance all classes defined by that unit.