| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <title>2. Enhancement</title><base href="display"><link rel="stylesheet" type="text/css" href="css/docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="manual.html" title="Apache OpenJPA 2.2 User's Guide"><link rel="up" href="ref_guide_pc.html" title="Chapter 5. Persistent Classes"><link rel="prev" href="ref_guide_pc.html" title="Chapter 5. Persistent Classes"><link rel="next" href="ref_guide_pc_interfaces.html" title="3. Managed Interfaces"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2. |
| Enhancement |
| </th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ref_guide_pc.html">Prev</a> </td><th width="60%" align="center">Chapter 5. |
| Persistent Classes |
| </th><td width="20%" align="right"> <a accesskey="n" href="ref_guide_pc_interfaces.html">Next</a></td></tr></table><hr></div><div class="section" title="2. Enhancement"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="ref_guide_pc_enhance">2. |
| Enhancement |
| </h2></div></div></div><div class="toc"><dl><dt><span class="section"><a href="ref_guide_pc_enhance.html#ref_guide_pc_enhance_build">2.1. |
| Enhancing at Build Time |
| </a></span></dt><dt><span class="section"><a href="ref_guide_pc_enhance.html#ref_guide_pc_enhance_runtime_container">2.2. |
| Enhancing JPA Entities on Deployment |
| </a></span></dt><dt><span class="section"><a href="ref_guide_pc_enhance.html#ref_guide_pc_enhance_runtime">2.3. |
| Enhancing at Runtime |
| </a></span></dt><dt><span class="section"><a href="ref_guide_pc_enhance.html#ref_guide_pc_enhance_dynamic">2.4. |
| Enhancing Dynamically at Runtime |
| </a></span></dt><dt><span class="section"><a href="ref_guide_pc_enhance.html#ref_guide_pc_enhance_unenhanced_types">2.5. |
| Omitting the OpenJPA enhancer |
| </a></span></dt></dl></div> |
| |
| <a class="indexterm" name="d5e11961"></a> |
| <a class="indexterm" name="d5e11963"></a> |
| <p> |
| In order to provide optimal runtime performance, flexible lazy loading, and |
| efficient, immediate dirty tracking, OpenJPA can use an <span class="emphasis"><em>enhancer |
| </em></span>. 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 <code class="literal">pc</code> in stack traces and |
| step-throughs. For example, if your entity has a <code class="methodname">getId</code> |
| method for persistent property <code class="literal">id</code>, and that method throws an |
| exception, the stack trace will report the exception from method <code class="methodname"> |
| pcgetId</code>. The line numbers, however, will correctly correspond to |
| the <code class="methodname">getId</code> method in your source file. |
| </p> |
| <div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="339"><tr><td><img src="img/enhancement.png"></td></tr></table></div> |
| <p> |
| The diagram above illustrates the compilation of a persistent class. |
| </p> |
| <p> |
| You can add the OpenJPA enhancer to your build process, or use Java 1.5's |
| instrumentation features to transparently enhance persistent classes when they |
| are loaded into the JVM. The following sections describe each option. |
| </p> |
| <div class="section" title="2.1. Enhancing at Build Time"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_enhance_build">2.1. |
| Enhancing at Build Time |
| </h3></div></div></div> |
| |
| <a class="indexterm" name="d5e11980"></a> |
| <p> |
| The enhancer can be invoked at build time |
| via its Java class, <code class="classname"> |
| org.apache.openjpa.enhance.PCEnhancer</code>. |
| </p> |
| <div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3> |
| <p> |
| You can also enhance via Ant; see |
| <a class="xref" href="ref_guide_integration.html#ref_guide_integration_enhance" title="1.2. Enhancer Ant Task">Section 1.2, “ |
| Enhancer Ant Task |
| ”</a>. |
| </p> |
| </div> |
| <div class="example"><a name="ref_guide_pc_enhance_enhancer"></a><p class="title"><b>Example 5.1. |
| Using the OpenJPA Enhancer |
| </b></p><div class="example-contents"> |
| |
| <pre class="programlisting"> |
| java org.apache.openjpa.enhance.PCEnhancer Magazine.java |
| </pre> |
| </div></div><br class="example-break"> |
| <p> |
| The enhancer accepts the standard set of command-line arguments defined by the |
| configuration framework (see <a class="xref" href="ref_guide_conf_devtools.html" title="3. Command Line Configuration">Section 3, “ |
| Command Line Configuration |
| ”</a> ), |
| along with the following flags: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> |
| <p> |
| <code class="literal">-directory/-d <output directory></code>: 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 <code class="filename">.class</code> file. |
| </p> |
| </li><li class="listitem"> |
| <p> |
| <code class="literal">-enforcePropertyRestrictions/-epr <true/t | false/f></code>: |
| 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. |
| </p> |
| </li><li class="listitem"> |
| <p> |
| <code class="literal">-addDefaultConstructor/-adc <true/t | false/f></code>: 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 <code class="literal"> |
| true</code>. |
| </p> |
| </li><li class="listitem"> |
| <p> |
| <code class="literal">-tmpClassLoader/-tcl <true/t | false/f></code>: 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 |
| <code class="literal">true</code>. Try setting this flag to <code class="literal">false</code> as a |
| debugging step if you run into class loading problems when running the enhancer. |
| </p> |
| </li></ul></div> |
| <p> |
| Each additional argument to the enhancer must be one of the following: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> |
| <p> |
| The full name of a class. |
| </p> |
| </li><li class="listitem"> |
| <p> |
| The .java file for a class. |
| </p> |
| </li><li class="listitem"> |
| <p> |
| The <code class="filename">.class</code> file of a class. |
| </p> |
| </li></ul></div> |
| <p> |
| If you do not supply any arguments to the enhancer, it will run on the classes |
| in your persistent class list (see <a class="xref" href="ref_guide_pc.html#ref_guide_pc_pcclasses" title="1. Persistent Class List">Section 1, “ |
| Persistent Class List |
| ”</a>). |
| You must, however, supply the classpath you wish the enhancer to run with. This |
| classpath must include, at minimum, the openjpa jar(s), persistence.xml and |
| the target classes. |
| </p> |
| <p> |
| 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. |
| </p> |
| <p> |
| 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. |
| </p> |
| </div> |
| <div class="section" title="2.2. Enhancing JPA Entities on Deployment"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_enhance_runtime_container">2.2. |
| Enhancing JPA Entities on Deployment |
| </h3></div></div></div> |
| |
| <a class="indexterm" name="d5e12025"></a> |
| <p> |
| The Java EE specification includes hooks to automatically enhance JPA entities |
| when they are deployed into a container. Thus, if you are using a Java EE-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. |
| </p> |
| <p> |
| If your application server does not support the Java EE enhancement hooks, |
| consider using the build-time enhancement described above, or the more general |
| runtime enhancement described in the next section. |
| </p> |
| </div> |
| <div class="section" title="2.3. Enhancing at Runtime"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_enhance_runtime">2.3. |
| Enhancing at Runtime |
| </h3></div></div></div> |
| |
| <a class="indexterm" name="d5e12033"></a> |
| <p> |
| OpenJPA includes a <span class="emphasis"><em>Java agent</em></span> for automatically enhancing |
| persistent classes as they are loaded into the JVM. Java agents are classes that |
| are invoked prior to your application's <code class="methodname">main</code> method. |
| OpenJPA's agent uses JVM hooks to intercept all class loading to enhance classes |
| that have persistence metadata before the JVM loads them. |
| </p> |
| <p> |
| 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 <a class="xref" href="ref_guide_pc.html#ref_guide_pc_pcclasses" title="1. Persistent Class List">Section 1, “ |
| Persistent Class List |
| ”</a>. If |
| you declare a persistent class list, OpenJPA will only search for |
| metadata for classes in that list. |
| </p> |
| <p> |
| To employ the OpenJPA agent, invoke <code class="literal">java</code> with the <code class="literal"> |
| -javaagent</code> set to the path to your OpenJPA jar file. |
| </p> |
| <div class="example"><a name="ref_guide_pc_enhance_runtime_ex"></a><p class="title"><b>Example 5.2. |
| Using the OpenJPA Agent for Runtime Enhancement |
| </b></p><div class="example-contents"> |
| |
| <pre class="programlisting"> |
| java -javaagent:/home/dev/openjpa/lib/openjpa.jar com.xyz.Main |
| </pre> |
| </div></div><br class="example-break"> |
| <p> |
| You can pass settings to the agent using OpenJPA's plugin syntax (see |
| <a class="xref" href="ref_guide_conf_plugins.html" title="4. Plugin Configuration">Section 4, “ |
| Plugin Configuration |
| ”</a>). The agent accepts the long |
| form of any of the standard configuration options |
| (<a class="xref" href="ref_guide_conf_devtools.html" title="3. Command Line Configuration">Section 3, “ |
| Command Line Configuration |
| ”</a> ). It also accepts the following |
| options, the first three of which correspond exactly to the same-named |
| options of the enhancer tool described in |
| <a class="xref" href="ref_guide_pc_enhance.html#ref_guide_pc_enhance_build" title="2.1. Enhancing at Build Time">Section 2.1, “ |
| Enhancing at Build Time |
| ”</a>: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> |
| <p> |
| <code class="literal">addDefaultConstructor</code> |
| </p> |
| </li><li class="listitem"> |
| <p> |
| <code class="literal">enforcePropertyRestrictions</code> |
| </p> |
| </li><li class="listitem"> |
| <p> |
| <code class="literal">scanDevPath</code>: 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. |
| </p> |
| </li><li class="listitem"> |
| <p> |
| <code class="literal">classLoadEnhancement</code>: Boolean controlling whether OpenJPA |
| load-time class enhancement should be available in this JVM execution. Default: |
| <code class="literal">true</code> |
| </p> |
| </li><li class="listitem"> |
| <p> |
| <code class="literal">runtimeRedefinition</code>: Boolean controlling whether OpenJPA |
| class redefinition should be available in this JVM execution. Default: |
| <code class="literal">true</code> |
| </p> |
| </li></ul></div> |
| <div class="example"><a name="ref_guide_pc_enhance_runtime_opt_ex"></a><p class="title"><b>Example 5.3. |
| Passing Options to the OpenJPA Agent |
| </b></p><div class="example-contents"> |
| |
| <pre class="programlisting"> |
| java -javaagent:/home/dev/openjpa/lib/openjpa.jar=addDefaultConstructor=false com.xyz.Main |
| </pre> |
| </div></div><br class="example-break"> |
| </div> |
| <div class="section" title="2.4. Enhancing Dynamically at Runtime"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_enhance_dynamic">2.4. |
| Enhancing Dynamically at Runtime |
| </h3></div></div></div> |
| |
| <p> |
| If a javaagent is not provided via the command line and |
| OpenJPA is running on the Oracle 1.6 SDK or IBM 1.6 JDK (SR8+), OpenJPA |
| will attempt to dynamically load the Enhancer that was |
| mentioned in the previous section. This support is |
| provided as an ease of use feature and it is not recommended |
| for use in a production system. Using this method of |
| enhancement has the following caveats: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> |
| <p> |
| The dynamic runtime enhancer is plugged into |
| the JVM during creation of the |
| EntityManagerFactory. Any Entity classes that |
| are loaded before the EntityManagerFactory is |
| created will not be enhanced. |
| </p> |
| </li><li class="listitem"> |
| <p> |
| The command line javaagent settings are not |
| configurable when using this method of |
| enhancement. |
| </p> |
| </li><li class="listitem"> |
| <p> |
| Just as with the Javaagent approach, if you |
| declare a persistent class list, then OpenJPA |
| will only search for metadata and try to |
| enhance the listed classes. |
| </p> |
| </li></ul></div> |
| <p> |
| When then dynamic enhancer is loaded, the following |
| informational message is logged: |
| </p><pre class="programlisting"> |
| [java] jpa.enhancement INFO [main] openjpa.Runtime - OpenJPA dynamically loaded the class enhancer. Any classes that were not enhanced at build time will be enhanced when they are loaded by the JVM. |
| </pre><p> |
| </p> |
| <p> |
| Setting the property openjpa.DynamicEnhancementAgent to false |
| will disable this function. |
| </p> |
| </div> |
| <div class="section" title="2.5. Omitting the OpenJPA enhancer"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_enhance_unenhanced_types">2.5. |
| Omitting the OpenJPA enhancer |
| </h3></div></div></div> |
| |
| <a class="indexterm" name="d5e12088"></a> |
| <p> |
| OpenJPA does not require that the enhancer be run. If you do not run the |
| enhancer, OpenJPA will fall back to one of several possible alternatives for |
| state tracking, depending on the execution environment. |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> |
| <span class="emphasis"><em>Deploy-time enhancement</em></span>: if you are running your |
| application inside a Java EE container, or another environment that supports |
| the JPA container contract, then OpenJPA will automatically perform class |
| transformation at deploy time. |
| </p></li><li class="listitem"><p> |
| <span class="emphasis"><em>Java 6 class retransformation</em></span>: if you are running your |
| application in a Java 6 environment, OpenJPA will attempt to dynamically |
| register a <code class="literal">ClassTransformer</code> that will redefine your |
| persistent classes on the fly to track access to persistent data. Additionally, |
| OpenJPA will create a subclass for each of your persistent classes. When |
| you execute a query or traverse a relation, OpenJPA will return an instance |
| of the subclass. This means that the <code class="literal">instanceof</code> operator |
| will work as expected, but <code class="literal">o.getClass()</code> will return the |
| subclass instead of the class that you wrote. |
| </p> |
| <p> |
| You do not need to do anything at all to get this behavior. OpenJPA will |
| automatically detect whether or not the execution environment is capable of |
| Java 6 class retransformation. |
| </p></li><li class="listitem"><p> |
| <span class="emphasis"><em>Java 5 class redefinition</em></span>: if you are running your |
| application in a Java 5 environment, and you specify the OpenJPA javaagent, |
| OpenJPA will use Java 5 class redefinition to redefine any persistent classes |
| that are not enhanced by the OpenJPA javaagent. Aside from the requirement |
| that you specify a javaagent on the command line, this behavior is exactly the |
| same as the Java 6 class retransformation behavior. Of course, since the |
| OpenJPA javaagent performs enhancement by default, this will only be available |
| if you set the <code class="literal">classLoadEnhancement</code> javaagent flag to |
| <code class="literal">false</code>, or on any classes that are skipped by the OpenJPA |
| runtime enhancement process for some reason. |
| </p></li><li class="listitem"><p> |
| <span class="emphasis"><em>Runtime Unenhanced Classes</em></span>: AKA state comparison and |
| subclassing. If you are running |
| in a Java 5 environment without a javaagent, or in a Java 6 environment that |
| does not support class retransformation, OpenJPA will still create subclasses |
| as outlined above. However, in some cases, OpenJPA may not be able to receive |
| notifications when you read or write persistent data. |
| </p> |
| <p> |
| </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3> |
| Runtime Unenhanced Classes has some known limitations which are discussed below |
| and documented in JIRA issue tracker on the OpenJPA website. As a result this option is |
| disabled by default. Support for this method of automatic enhancement may be |
| enabled via the <a class="xref" href="ref_guide_conf_openjpa.html#openjpa.RuntimeUnenhancedClasses" title="5.63. openjpa.RuntimeUnenhancedClasses">Section 5.63, “openjpa.RuntimeUnenhancedClasses”</a> option. |
| </div><p> |
| </p> |
| <p> |
| To enable Runtime Unenhanced Classes for a specific persistence unit, add the following property to persistence.xml: |
| </p><pre class="programlisting"> |
| <properties> |
| . . . |
| <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/> |
| . . . |
| <properties> |
| </pre><p> |
| </p> |
| <p> |
| If you are using <span class="emphasis"><em>property access</em></span> for your persistent data, |
| then OpenJPA will be able to track all accesses for instances that you load |
| from the database, but not for instances that you create. This is because |
| OpenJPA will create new instances of its dynamically-generated subclass when |
| it loads data from the database. The dynamically-generated subclass has |
| code in the setters and getters that notify OpenJPA about persistent data |
| access. This means that new instances that you create will be subject to |
| state-comparison checks (see discussion below) to compute which fields to |
| write to the database, and that OpenJPA will ignore requests to evict |
| persistent data from such instances. In practice, this is not a particularly |
| bad limitation, since OpenJPA already knows that it must insert all field |
| values for new instances. So, this is only really an issue if you flush |
| changes to the database while inserting new records; after such a flush, |
| OpenJPA will need to hold potentially-unneeded hard references to the |
| new-flushed instances. |
| </p> |
| <p> |
| If you are using <span class="emphasis"><em>field access</em></span> for your persistent data, |
| then OpenJPA will not be able to track accesses for any instances, including |
| ones that you load from the database. So, OpenJPA will perform state-comparison |
| checks to determine which fields are dirty. These state comparison checks are |
| costly in two ways. First, there is a performance penalty at flush / commit |
| time, since OpenJPA must walk through every field of every instance to determine |
| which fields of which records are dirty. Second, there is a memory penalty, |
| since OpenJPA must hold hard references to all instances that were loaded at |
| any time in a given transaction, and since OpenJPA must keep a copy of all |
| the initial values of the loaded data for later comparison. Additionally, |
| OpenJPA will ignore requests to evict persistent state for these types of |
| instances. Finally, the default lazy loading configuration will be ignored for |
| single-valued fields (one-to-one, many-to-one, and any other non-collection |
| or non-map field that has a lazy loading configuration). If you use fetch |
| groups or programmatically configure your fetch plan, OpenJPA will obey these |
| directives, but will be unable to lazily load any data that you exclude from |
| loading. As a result of these limitations, it is not recommended that you use |
| field access if you are not either running the enhancer or using OpenJPA with |
| a javaagent or in a Java 6 environment. |
| </p></li></ul></div> |
| </div> |
| </div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ref_guide_pc.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ref_guide_pc.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ref_guide_pc_interfaces.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 5. |
| Persistent Classes |
| </td><td width="20%" align="center"><a accesskey="h" href="manual.html">Home</a></td><td width="40%" align="right" valign="top"> 3. Managed Interfaces</td></tr></table></div></body></html> |