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.
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”.
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.
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.
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.
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.