Welcome!

From the Desk of Oracle ACE Director

Chris Muir

Subscribe to Chris Muir: eMailAlertsEmail Alerts
Get Chris Muir via: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Related Topics: Intel XML, Oracle Journal, XML Magazine, Java Developer Magazine, CIO/CTO Update

Blog Feed Post

Creating an ADF Library JAR

Using ojdeploy and Ant

Projects and the application itself in Oracle's JDeveloper 11g are capable of generating different deployment files at design time, including WAR files, EAR files, JAR files and other standard Java EE archive types. In addition JDev can generate a special JAR type specific to ADF development known as an ADF library. An ADF library differs from standard JARs in that the ADF library includes additional metadata files and constructs required for ADF application development.

To create an ADF library JAR you first need to setup an associated ADF library JAR via the project properties. This is well document in the Fusion Guide.

From here there are essentially two ways to actually generate the ADF library JAR. The first is within the IDE via the project right-click deploy options, and applicable to programmers developing in their JDev IDE.

The other option particularly important to build environments is the ojdeploy utility. This tool can be called via the command line or an Ant script, and is necessary for generating ADF library JAR files with the required metadata files and other ADF constructs.

In specifically considering the ant script option for ojdeploy, JDev will create a basic Ant script for building your applications via the New Gallery -> Ant -> Buildfile from Project option. In the dialog that displays selecting the "Include Packaging Tasks (uses ojdeploy)" checkbox ensures the generated Ant script includes an ojdeploy target:

The resulting Ant file will look something like this:

<?xml version="1.0" encoding="UTF-8" ?>
<project name="ViewController" default="all" basedir=".">
<property file="build.properties"/>
<path>....snipped....</path>
<target name="init">
<tstamp/>
<mkdir dir="${output.dir}"/>
</target>
<target name="all" description="Build the project" depends="deploy,compile,copy"/>
<target name="clean" description="Clean the project">
<delete includeemptydirs="true" quiet="true">
<fileset dir="${output.dir}" includes="**/*"/>
</delete>
</target>
<target name="deploy" description="Deploy JDeveloper profiles" depends="init,compile">
<taskdef name="ojdeploy" classname="oracle.jdeveloper.deploy.ant.OJDeployAntTask" uri="oraclelib:OJDeployAntTask"
classpath="${oracle.jdeveloper.ant.library}"/>
<ora:ojdeploy xmlns:ora="oraclelib:OJDeployAntTask" executable="${oracle.jdeveloper.ojdeploy.path}"
ora:buildscript="${oracle.jdeveloper.deploy.dir}/ojdeploy-build.xml"
ora:statuslog="${oracle.jdeveloper.deploy.dir}/ojdeploy-statuslog.xml">
<ora:deploy>
<ora:parameter name="workspace" value="${oracle.jdeveloper.workspace.path}"/>
<ora:parameter name="project" value="${oracle.jdeveloper.project.name}"/>
<ora:parameter name="profile" value="${oracle.jdeveloper.deploy.profile.name}"/>
<ora:parameter name="nocompile" value="true"/>
<ora:parameter name="outputfile" value="${oracle.jdeveloper.deploy.outputfile}"/>
</ora:deploy>
</ora:ojdeploy>
</target>
<target name="compile" description="Compile Java source files" depends="init">
<javac destdir="${output.dir}" classpathref="classpath" debug="${javac.debug}" nowarn="${javac.nowarn}"
deprecation="${javac.deprecation}" encoding="UTF-8" source="1.6" target="1.6">
<src path="src"/>
</javac>
</target>
<target name="copy" description="Copy files to output directory" depends="init">
<patternset id="copy.patterns">
<include name="**/*.gif"/>
<include name="**/*.jpg"/>
<include name="**/*.jpeg"/>
<include name="**/*.png"/>
<include name="**/*.properties"/>
<include name="**/*.xml"/>
<include name="**/*.ejx"/>
<include name="**/*.xcfg"/>
<include name="**/*.cpx"/>
<include name="**/*.dcx"/>
<include name="**/*.sva"/>
<include name="**/*.wsdl"/>
<include name="**/*.ini"/>
<include name="**/*.tld"/>
<include name="**/*.tag"/>
<include name="**/*.xlf"/>
<include name="**/*.xsl"/>
<include name="**/*.xsd"/>
</patternset>
<copy todir="${output.dir}">
<fileset dir="src">
<patternset refid="copy.patterns"/>
</fileset>
</copy>
</target>
</project>

In particular notice the Ant targets: init, clean, deploy, compile and copy. Note within the deploy target a call to the ojdeploy utility.

Now you'd think with these 5 targets generated by JDeveloper that they are all co-related and have dependencies. You can even see the deploy-ojdeploy target has dependencies on the init and compile targets. Unfortunately this is misleading.

The ojdeploy utility written by Oracle is in fact capable of doing all the other targets' tasks. The utility takes care of creating/initializing the destination directories, it cleans and compiles the specified application or project, and it takes care of copying all class files. In fact if you leave the other targets in the Ant script this can interfere with the operation of the ojdeploy utility and you should in fact remove them. Instead you should have something like this:


<project name="ViewController" default="all" basedir=".">
<property file="build.properties"/>
<path>....snipped....
<target name="deploy" description="Deploy JDeveloper profiles" depends="init,compile">
<taskdef name="ojdeploy" classname="oracle.jdeveloper.deploy.ant.OJDeployAntTask" uri="oraclelib:OJDeployAntTask"
classpath="${oracle.jdeveloper.ant.library}"/>
<ora:ojdeploy xmlns:ora="oraclelib:OJDeployAntTask" executable="${oracle.jdeveloper.ojdeploy.path}"
ora:buildscript="${oracle.jdeveloper.deploy.dir}/ojdeploy-build.xml"
ora:statuslog="${oracle.jdeveloper.deploy.dir}/ojdeploy-statuslog.xml">
<ora:deploy>
<ora:parameter name="workspace" value="${oracle.jdeveloper.workspace.path}"/>
<ora:parameter name="project" value="${oracle.jdeveloper.project.name}"/>
<ora:parameter name="profile" value="${oracle.jdeveloper.deploy.profile.name}"/>
<ora:parameter name="outputfile" value="${oracle.jdeveloper.deploy.outputfile}"/>
</ora:deploy>
</ora:ojdeploy>
</target>
</project>

If you've looked very carefully, you might have noticed I removed the nocompile option for ojdeploy. Bizarrely this boolean option takes three forms: true, false, and, the one you need to use to ensure the correct ADF constructs (such as task-flow-registry.xml) are added to the end ADF library JAR, is remove the nocompile option completely.

(This is bug 9000629 – closed by Support, not considered a bug, but confusing and not intuitive by design)

On the Windows platform you need to be careful that any paths you include in the ojdeploy target within the Ant script (either directly or indirectly via a properties file) exactly match the case of the Windows file system, otherwise similar issues can occur.

(Another bug 10028816 – confirmed bug – fixed 11.1.1.4.0 – patch available for 11.1.1.2.0)

Finally there's also a bug in the ojdeploy workspace option that it can't support the Ant script ${user.dir} property. This isn't applicable to the example above but I thought worth documenting.

(Bug 10028879 – confirmed bug – fixed 11.1.1.4.0 – patch available for 11.1.1.2.0)

Entirely separately to generating ADF libraries, if you wish to use the ojdeploy utility to create an EAR via the workspace, you do this by dropping the project option leaving the workspace, profile and outputfile options. If you do this under JDev 11.1.1.2.0 specifically you'll see the error message "Missing <workspace>, <project> or <profile> parameter in <deploy> element", caused by a bug in the ojdeploy utility, of which there is a patch available.

(Bug 9135159 – confirmed bug – fixed 11.1.1.3.0 – patch available for 11.1.1.2.0)

Addendum

All the above documented via JDev 11.1.1.2.0.

Read the original blog entry...

More Stories By Chris Muir

Chris Muir, an Oracle ACE Director, senior developer and trainer, and frequent blogger at http://one-size-doesnt-fit-all.blogspot.com, has been hacking away as an Oracle consultant with Australia's SAGE Computing Services for too many years. Taking a pragmatic approach to all things Oracle, Chris has more recently earned battle scars with JDeveloper, Apex, OID and web services, and has some very old war-wounds from a dark and dim past with Forms, Reports and even Designer 100% generation. He is a frequent presenter and contributor to the local Australian Oracle User Group scene, as well as a contributor to international user group magazines such as the IOUG and UKOUG.