2. Enhancement

2.1. Enhancing at Build Time
2.2. Enhancing JPA Entities on Deployment
2.3. Enhancing at Runtime
2.4. Serializing Enhanced Types

In order to provide optimal runtime performance, flexible lazy loading, and efficient, immediate dirty tracking, OpenJPA uses an enhancer. An enhancer is a tool that automatically adds code to your persistent classes after you have written them. The enhancer post-processes the bytecode generated by your Java compiler, adding the necessary fields and methods to implement the required persistence features. This bytecode modification perfectly preserves the line numbers in stack traces and is compatible with Java debuggers. In fact, the only change to debugging is that the persistent setter and getter methods of entity classes using property access will be prefixed with pc in stack traces and step-throughs. For example, if your entity has a getId method for persistent property id, and that method throws an exception, the stack trace will report the exception from method pcgetId. The line numbers, however, will correctly correspond to the getId method in your source file.

The diagram above illustrates the compilation of a persistent class.

You can add the OpenJPA enhancer to your build process, or use Java 1.5's new instrumentation features to transparently enhance persistent classes when they are loaded into the JVM. The following sections describe each option.

2.1. Enhancing at Build Time

The enhancer can be invoked at build time via the included openjpac script or via its Java class, org.apache.openjpa.enhance.PCEnhancer.


You can also enhance via Ant; see Section 1.2, “Enhancer Ant Task”.

Example 5.1. Using the OpenJPA Enhancer

openjpac Magazine.java

The enhancer accepts the standard set of command-line arguments defined by the configuration framework (see Section 3, “Command Line Configuration”), along with the following flags:

  • -directory/-d <output directory>: Path to the output directory. If the directory does not match the enhanced class' package, the package structure will be created beneath the directory. By default, the enhancer overwrites the original .class file.

  • -enforcePropertyRestrictions/-epr <true/t | false/f>: Whether to throw an exception when it appears that a property access entity is not obeying the restrictions placed on property access. Defaults to false.

  • -addDefaultConstructor/-adc <true/t | false/f>: The spec requires that all persistent classes define a no-arg constructor. This flag tells the enhancer whether to add a protected no-arg constructor to any persistent classes that don't already have one. Defaults to true.

  • -tmpClassLoader/-tcl <true/t | false/f>: Whether to load persistent classes with a temporary class loader. This allows other code to then load the enhanced version of the class within the same JVM. Defaults to true. Try setting this flag to false as a debugging step if you run into class loading problems when running the enhancer.

Each additional argument to the enhancer must be one of the following:

  • The full name of a class.

  • The .java file for a class.

  • The .class file of a class.

If you do not supply any arguments to the enhancer, it will run on the classes in your persistent class list (see Section 1, “Persistent Class List”).

You can run the enhancer over classes that have already been enhanced, in which case it will not further modify the class. You can also run it over classes that are not persistence-capable, in which case it will treat the class as persistence-aware. Persistence-aware classes can directly manipulate the persistent fields of persistence-capable classes.

Note that the enhancement process for subclasses introduces dependencies on the persistent parent class being enhanced. This is normally not problematic; however, when running the enhancer multiple times over a subclass whose parent class is not yet enhanced, class loading errors can occur. In the event of a class load error, simply re-compile and re-enhance the offending classes.

2.2. Enhancing JPA Entities on Deployment

The JEE 5 specification includes hooks to automatically enhance JPA entities when they are deployed into a container. Thus, if you are using a JEE 5-compliant application server, OpenJPA will enhance your entities automatically at runtime. Note that if you prefer build-time enhancement, OpenJPA's runtime enhancer will correctly recognize and skip pre-enhanced classes.

If your application server does not support the JEE 5 enhancement hooks, consider using the build-time enhancement described above, or the more general runtime enhancement described in the next section.

2.3. Enhancing at Runtime

OpenJPA includes a Java agent for automatically enhancing persistent classes as they are loaded into the JVM. Java agents are classes that are invoked prior to your application's main method. OpenJPA's agent uses JVM hooks to intercept all class loading to enhance classes that have persistence metadata before the JVM loads them.


Java agents are new to Java 5; if you are using a previous Java version, you must use OpenJPA's build-time enhancement option.

Searching for metadata for every class loaded by the JVM can slow application initialization. One way to speed things up is to take advantage of the optional persistent class list described in Section 1, “Persistent Class List”. If you declare a persistent class list, OpenJPA will only search for metadata for classes in that list.

To employ the OpenJPA agent, invoke java with the -javaagent set to the path to your org.apache.openjpa.jar or openjpa-runtime.jar file.

Example 5.2. Using the OpenJPA Agent for Runtime Enhancement

java -javaagent:/home/dev/openjpa/lib/org.apache.openjpa.jar com.xyz.Main

You can pass settings to the agent using OpenJPA's plugin syntax (see Section 4, “Plugin Configuration”). The agent accepts the long form of any of the standard configuration options (Section 3, “Command Line Configuration”). It also accepts the following options, the first three of which correspond exactly to to the same-named options of the enhancer tool described in Section 2.1, “Enhancing at Build Time”:

  • addDefaultConstructor

  • jdoEnhance

  • enforcePropertyRestrictions

  • scanDevPath: Boolean indicating whether to scan the classpath for persistent types if none have been configured. If you do not specify a persistent types list and do not set this option to true, OpenJPA will check whether each class loaded into the JVM is persistent, and enhance it accordingly. This may slow down class load times significantly.

Example 5.3. Passing Options to the OpenJPA Agent

java -javaagent:/home/dev/openjpa/lib/org.apache.openjpa.jar=jdoEnhance=true,addDefaultConstructor=false com.xyz.Main

2.4. Serializing Enhanced Types

By default, OpenJPA maintains serialization compatibility between the enhanced and unenhanced versions of a class. This allows you to serialize instances between a server using OpenJPA and a client that does not have access to enhanced classes or OpenJPA libraries. In some cases, however, you can make the persist and attach processes more robust and efficient by allowing breaks in serialization compatibility. See Section 1.3, “Defining the Detached Object Graph” for details.