Enhancing with Ant

Background

Enhancement is a JDO standard process to inject code into the persistent class. The injected code provides the basis of the solid and transparent object persistence specified by JDO.

In this quick tutorial you will learn how to use Apache Ant to compile and enhance persistent classes.

Enhancement

DataNucleus provides an Ant task to enhance files and all you have to do is set up some parameters, but before enhancing files with the DataNucleus Enhancer for Ant, let's look at a complete Ant build file specially created to compile, enhance and generate archive files (jar, war).

Enhancer Task

The Ant build file provided here as example is divided in many targets as like clean, compile, enhance, distribution and others. The one we are interested is the enhance.

This first section of the target enhance defines the classpath to use for enhancement. In this classpath we put the datanucleus-core.jar + datanucleus-api-jdo.jar/datanucleus-api-jpa.jar DataNucleus dependencies + Your Persistent Classes (.class) + Your JDO Classes (.jdo) + Your dependencies.

<!-- the classpath to enhance -->
<path id="module.enhancer.classpath">
    <pathelement location="${module.classes.dir}"/>
    <path refid="module.lib.classpath"/>
</path>

In the second section, we define the DataNucleus Enhancer task.

<!-- define the task enhancer -->
<taskdef name="nucleusenhancer"
    classpathref="module.enhancer.classpath" 
    classname="org.datanucleus.enhancer.EnhancerTask" />                           

With the DataNucleus Enhancer task defined, we are now able to use it. It's important to correctly define the classpath. See this reference for further information on attributes that can be configured for the enhancer.

<!-- enhance -->
<nucleusenhancer classpathref="module.enhancer.classpath"/>

Full example

This example is composed of three files, build.xml, module.properties and module.xml. In the file build.xml we load the properties for the module and call the distribution target defined in the module.xml file, which compiles, enhance and create an archive file. In the module.properties file we define the variables to point to the location of files.

                
                
#######################################
# module.properties
#######################################

#######################################
# project
#######################################
Name=my-module-name
name=${Name}
version=1.0

#######################################
# ANT
#######################################
build.default.target = distribution

#######################################
# PROJECT
#######################################
project.build.debug=on
project.lib.dir=lib

#######################################
# SAMPLE FOR WAR MODULE
#######################################
module.dir=./WebContent
module.lib.dir=${module.dir}/WEB-INF/lib
module.lib2.dir=/home/user/lib
module.classes.dir=${module.dir}/WEB-INF/classes
module.src.java.dir=./src/java
module.build.debug=on
module.archive.dist.dir=dist
module.archive.dist.file=${name}.war
module.archive.files=**/*

#######################################
# SAMPLE FOR JAR MODULE (commented out)
#######################################
#module.dir=./
#module.lib.dir=${module.dir}/lib
#module.lib2.dir=/home/user/lib
#module.classes.dir=${module.dir}/classes
#module.src.java.dir=./src
#module.build.debug=on
#module.archive.dist.dir=dist
#module.archive.dist.file=${name}.jar
#module.archive.files=**/*

                
                
                
<!--
===================================================================
build.xml
===================================================================
-->
<project name="project" default="default">

    <import file="module.xml"/>
    
    <!--
    ===================================================================
    environment
    ===================================================================
    -->
    <property environment="env"/>
    <property name="project.location" location="."/>

    <!--
    ===================================================================
    TARGET : default
    ===================================================================
    -->
    <target name="default">
        <echo message="==================================================================="/>
        <echo message="Welcome to the build."/>
        <echo message="==================================================================="/>
        <property file="${project.location}/module.properties"/>
        <antcall target="distribution"/>
    </target>
    
</project>

                
                

<!--
===================================================================
module.xml
===================================================================
-->
<project name="module" default="distribution">

    <!--
    ===================================================================
    environment
    ===================================================================
    -->
    <property environment="env"/>
    <property name="project.location" location="."/>

    <!--
    ===================================================================
    TARGET : default
    ===================================================================
    -->
    <target name="default">
        <echo message="==================================================================="/>
        <echo message="Welcome to the build."/>
        <echo message="==================================================================="/>
        <antcall target="${build.default.target}"/>
    </target>
    
    <!--
    ===================================================================
    CONFIGURATION: MODULE
    ===================================================================
    -->

    <!-- libs necessary to build the module -->
    <path id="module.lib.classpath">
        <fileset dir="${module.lib.dir}">
            <include name="**/*.jar"/>
        </fileset>
        <fileset dir="${module.lib2.dir}">
            <include name="**/*.jar"/>
        </fileset>
    </path>

    <!-- the classpath to compile -->
    <path id="module.compile.classpath">
        <pathelement location="${module.classes.dir}"/>
        <path refid="module.lib.classpath"/>
    </path>

    <!--
    ===================================================================
    TARGET : clean
    ===================================================================
    -->
    <target name="clean">
        <delete includeEmptyDirs="true" quiet="true">
            <fileset dir="${module.classes.dir}" includes="**/*.class,**/*.properties,**/*.*"/>
        </delete>
    </target>

    <!--
    ===================================================================
    TARGET : prepare
    ===================================================================
    -->
    <target name="prepare">
        <mkdir dir="${module.classes.dir}"/>
    </target>

    <!--
    ===================================================================
    TARGET : compile
    ===================================================================
    -->
    <target name="compile" depends="clean,prepare">
        <echo message="==================================================================="/>
        <echo message="MODULE ${module.name} Compile configuration:"/>
        <echo message="java.dir       = ${module.src.java.dir}"/>
        <echo message="classes.dir    = ${module.classes.dir}"/>
        <echo message="==================================================================="/>
        <javac srcdir="${module.src.java.dir}"
               destdir="${module.classes.dir}"
               debug="${module.build.debug}"
               classpathref="module.compile.classpath">
            <include name="**/*.java"/>
        </javac>

    </target>

    <!--
    ===================================================================
    TARGET : copy metadata files
    ===================================================================
    -->
    <target name="copy.metadata">
        <copy todir="${module.classes.dir}">
            <fileset dir="${module.src.java.dir}"
                     includes="**/*.jdo,**/*.properties,**/*.dtd,**/*.xml"/>
        </copy>
    </target>

    <!--
    ===================================================================
    TARGET : enhance
    ===================================================================
    -->
    <target name="enhance" depends="compile,copy.metadata">

        <echo message="==================================================================="/>
        <echo message="Enhancing the MODULE files"/>
        <echo message="==================================================================="/>

        <!-- the classpath to enhance -->
        <path id="module.enhancer.classpath">
            <pathelement location="${module.classes.dir}"/>
            <path refid="module.lib.classpath"/>
        </path>

        <!-- define the task enhancer -->
        <taskdef name="nucleusenhancer"
                 classpathref="module.enhancer.classpath"
                 classname="org.datanucleus.enhancer.EnhancerTask" />

        <!-- enhance -->
        <nucleusenhancer classpathref="module.enhancer.classpath"/>

    </target>

    <!--
    ===================================================================
    TARGET : modulearchive
    ===================================================================
    -->
    <target name="modulearchive" depends="enhance">
        <mkdir dir="${module.archive.dist.dir}"/>
        <delete file="${module.archive.dist.dir}/${module.archive.dist.file}"/>
        <zip zipfile="${module.archive.dist.dir}/${module.archive.dist.file}">
            <zipfileset  dir="${module.classes.dir}"  prefix="" includes="**/*"/>
            <zipfileset  dir="${module.dir}"  prefix="" includes="${module.archive.files}"/>
        </zip>
    </target>

    <!--
    ===================================================================
    TARGET : distribution
    ===================================================================
    -->
    <target name="distribution" depends="modulearchive">
        <echo message=""/>
        <echo message="==================================================================="/>
        <echo message="Module file ready at: ${module.archive.dist.dir}/${module.archive.dist.file}"/>
        <echo message="==================================================================="/>
        <echo message=""/>
    </target>
</project>