Ruben Laguna's blog

Sep 16, 2009 - 3 minute read - Comments - ant build build.xml classnotfoundexception classpath enhancer jpa netbeans openjpa openjpac task

OpenJPA Enhancer Ant task in a Netbeans project

In the build.xml of the project (likely this will be a Java Class Library project), override -post-compile or -pre-jar and invoke <openjpac/>. You will need to add the build/classes and the openjpa jars to <taskdef/> and <openjpac/>. The <openjpac/> will enhance all classes mentioned in persistence.xml (which has to be in the classpath)

<?xml version="1.0" encoding="UTF-8"?>
<project name="JpaEntitiesLibrary" default="default" basedir=".">
    <description>Builds, tests, and runs the project JpaEntitiesLibrary.</description>
    <import file="nbproject/build-impl.xml"/>

    <target name="-post-compile">
        <echo message="begin openJPAC"/>
        <path id="openjpa.path.id">
        <pathelement location="${build.classes.dir}"/>

        <!-- Adding the OpenJPA jars into the classpath -->
        <fileset dir="C:\Users\ecerulm\Downloads\apache-openjpa-1.2.1-binary\apache-openjpa-1.2.1\lib" includes="*.jar"/>

        <!--  or if you create a OpenJPA Library you can use that instead  -->
        <!--<pathelement path="${libs.OpenJPA.classpath}"/>-->
        </path>

        <taskdef name="openjpac" classname="org.apache.openjpa.ant.PCEnhancerTask">
            <classpath refid="openjpa.path.id"/>
        </taskdef>

        <openjpac>
            <classpath refid="openjpa.path.id"/>
        </openjpac>
        <echo message="end openJPAC"/>
    </target>

</project>

You can refer to the OpenJPA jars by either a <fileset> with the file path to the OpenJPA directory or by refererring to a Netbeans Library instead. You can create a OpenJPA Library via Tools ⇒ Libraries ⇒ New Library and add all the jars to the Library. If you name the library “OpenJPA” then you can refer to its classpath with <pathelement path="${libs.OpenJPA.classpath}"/>. See the commented code in the build.xml above.

IMPORTANT+: You may be tempted to put the <path> and the <taskdef> outside the <target>. I strongly disencorage this. If you do so then you need to ensure that ./build/classes directory is there before <path> is evaluated otherwise openjpac will fail to locate the META-INF/persistence.xml. So when you do an ant clean, the build/classes is deleted. If you do a ant jar after the ant clean, the build/classes will not be picked up by path and it will fail with a

 [openjpac] <openjpa-1.2.1-r752877:753278 fatal user error> org.apache.openjpa.u
til.MetaDataException: MetaDataFactory could not be configured (conf.newMetaData
FactoryInstance() returned null). This might mean that no configuration properti
es were found. Ensure that you have a META-INF/persistence.xml file, that it is
available in your classpath, or that the properties file you are using for confi
guration is available. If you are using Ant, please see the <properties> or <pro
pertiesFile> attributes of the task's nested <config> element. This can also occ
ur if your OpenJPA distribution jars are corrupt, or if your security policy is
overly strict.
 [openjpac]     at org.apache.openjpa.meta.MetaDataRepository.initializeMetaData
Factory(MetaDataRepository.java:1567)

Although you can ensure that build/classes is always there overriding -post-clean and creating it there with something like:

<target name="-post-clean">
<mkdir dir="${build.classes.dir}"/>
</target>

Then you will fall into a second problem: ${build.classes.dir} variable is not accesible outside the <target>. That variable is loaded through -init-project target. So you will be forced to use something like ./build/classes instead of a proper ${build.classes.dir}. So it’s better to define the task inside the target.

By the way, if you don’t set properly the classpath you will probably get an exception like this

java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: com.rubenlaguna.jpaentities.Notes
at serp.util.Strings.toClass(Strings.java:164)
at serp.util.Strings.toClass(Strings.java:108)
at serp.bytecode.BCClass.getType(BCClass.java:566)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:249)
at org.apache.openjpa.enhance.PCEnhancer.run(PCEnhancer.java:4493)
at org.apache.openjpa.ant.PCEnhancerTask.executeOn(PCEnhancerTask.java:89)
at org.apache.openjpa.lib.ant.AbstractTask.execute(AbstractTask.java:172)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor75.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
at org.apache.tools.ant.module.bridge.impl.BridgeImpl.run(BridgeImpl.java:278)
at org.apache.tools.ant.module.run.TargetExecutor.run(TargetExecutor.java:497)
at org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:151)
java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: com.rubenlaguna.jpaentities.Notes
at serp.util.Strings.toClass(Strings.java:164)
at serp.util.Strings.toClass(Strings.java:108)
at serp.bytecode.BCClass.getType(BCClass.java:566)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:249)
at org.apache.openjpa.enhance.PCEnhancer.run(PCEnhancer.java:4493)
at org.apache.openjpa.ant.PCEnhancerTask.executeOn(PCEnhancerTask.java:89)
at org.apache.openjpa.lib.ant.AbstractTask.execute(AbstractTask.java:172)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor75.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
at org.apache.tools.ant.module.bridge.impl.BridgeImpl.run(BridgeImpl.java:278)
at org.apache.tools.ant.module.run.TargetExecutor.run(TargetExecutor.java:497)
at org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:151)

References:

Derby 10.5 "OFFSET/FETCH" and JPA Adding a Google Search Web Element to a Wordpress theme