Oracle ADF and Gradle integration – part#1: Assembling ADF project using OJDeploy

Oracle ADF and Gradle integration – part#1: Assembling ADF project using OJDeploy

Gradle is a very powerful build automation system which allows you to build near everything – starting from Java through .NET ending up C++ projects. In this post I’ll show you basic ADF-Gradle integration that is a good starting point for further extensions like libraries dependency management or integration with Jenkins.

After this tutorial you should be able to integrate any ADF project with Gradle.  In next tutorials I’ll show you how to use Gradle to manage ADF library dependencies.

Overview:

  • Before we start
    • Sample application
    • Gradle – what you should know
      • Installation
      • Initializing Gradle project
      • Running tasks
  • Gradle – integration with ADF project
    • Prepare ojdeploy-buildfile.xml file
    • Create custom Gradle tasks
    • Tasks implementation
      • Task: checkAdfEnvironment
      • Task: clean
      • Task: assemble
    • Collecting all together – Test
  • What’s next?

 


Before we start

Sample application

For the purposes of this tutorial I’ll use an application from my previous post, where I showed you how to create simple ADF application which use Oracle Database Express Edition 11g installed in Docker container. You can do it yourself by watching the video start from 5:55 or you can download sample application.

The zip archive contains ADF workspace and gradle-wrapper.

.
├── ADFGradle           #ADF workspace
│   ├── ADFGradle.jws
│   ├── Model
│   ├── src
│   └── ViewController
└── gradle-wrapper      #Gradle wrapper
    ├── gradle
    ├── gradlew
    └── gradlew.bat

 

Gradle – what you should know

Gradle is a very similar tool to Maven and Ant. In my opinion it combines the best features of both build tools. I hope you will see it too.

Gradle project contains build.gradle file which is the equivalent of Maven pom.xml file.

Installation

You have several ways to run Gralde project tasks:

  • You can download and install Gradle tool in your OS.
  • You can install it via package manager i.e.
    sudo apt-get install gradle
    sudo yum install gradle
  • You can use an IDE like IntelliJ IDEA which supports Gradle.
  • You can use Gradle Wrapper. It’ll download necessary Gradle distribution during the first use.

Initializing Gradle project

For initialize Gradle project go to your project directory and run one of the commands listed below:

cd ~/your-project-directory

#Use one of
gradle init #Initialize Gradle Project
gradle wrapper #Initialize Gradle project and generate Gradle Wrapper

Running tasks

Go to the project the Gradle project directory and run:

cd ~/my-gradle-project

gradle tasks #display available project tasks
gradle clean assemble #perform two tasks clean workspace and build artifacts
gradle clean assemble -PsomeProjectProperty=someValue #pass project property

#if you use Gradle Wrapper:
gradlew tasks #display available project tasks
gradlew clean assemble #perform two tasks clean workspace and build artifacts
gradlew clean assemble -PsomeProjectProperty=someValue #pass project property

 


Gradle – integration with ADF project

Download sample ADF application, unzip it and go to the ADF workspace directory.

.
├── ADFGradle           #ADF workspace
│   ├── ADFGradle.jws
│   ├── Model
│   ├── src
│   └── ViewController
└── gradle-wrapper      #Gradle wrapper
    ├── gradle
    ├── gradlew
    └── gradlew.bat

 

Create adf-gradle directory and initialize Gradle project inside. If you don’t have Gradle installed, you can copy files from gradle-wrapper into the ADFGradle/adf-gradle directory.

After all create both build.gradle and ojdeploy-buildfile.xml files in ADFGradle/adf-gradle directory

cd ADFGradle
mkdir adf-gradle
cd adf-gradle

#initialize Gradle wrapper by running one of:
gradle wrapper
cp -R ../../gradle-wrapper/* ./

#create empty build.gradle file
touch build.gradle
touch ojdeploy-buildfile.xml

Our workspace should look like below.

.
├── ADFGradle
│   ├── adf-gradle
│   │   ├── build.gradle
│   │   ├── ojdeploy-buildfile.xml
│   │   ├── gradle
│   │   ├── gradlew
│   │   └── gradlew.bat
│   ├── ADFGradle.jws
│   ├── Model
│   ├── ViewController
│   └── src
└── gradle-wrapper
    ├── gradle
    │   └── wrapper
    ├── gradlew
    └── gradlew.bat

Prepare ojdeploy-buildfile.xml file

Put the following content into ojdeploy-buildfile.xml file. If you want to know more about the file just write me a message in comments at the bottom.

<?xml version = '1.0' standalone = 'yes'?>
<ojdeploy-build basedir=".">
    <defaults/>
    <deploy command="deployToArchive">
        <parameter name="workspace" value="${app.workspace.dir}/ADFGradle.jws"/>
        <parameter name="profile" value="DockerDBTest_Project1_DockerDBTest"/>
    </deploy>
</ojdeploy-build>

 

Create custom Gradle tasks

Edit build.gradle file and specify project group and version . Define two tasks as below:

  • clean – this is equivalent of mvn clean task
  • assemble – this is equivalent of mvn package task

Pay attention to tasks properties (group, description, dependsOn, mustRunAfter) and doLast section. At this moment let’s mock doLast sections by printing appropriate messages. We will finish them later.

group 'com.bettercoding'
version '1.0-SNAPSHOT'

task clean {
    group "oracle-adf"
    description "Clean ADF workspace"
    doLast {
        println "Cleaning project ${project.name}"
    }
}

task assemble {
    group "oracle-adf"
    description "Build ADF artficats"
    mustRunAfter clean
    dependsOn clean
    doLast {
        println "Assembled artifact ${project.group}:${project.name}-${project.version}"
    }
}

Run gradlew tasks command to display available tasks.

better-coding@bc-vbox:~/jdeveloper/mywork/ADFGradle/adf-gradle$ ./gradlew tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'adf-gradle'.
components - Displays the components produced by root project 'adf-gradle'. [incubating]
dependencies - Displays all dependencies declared in root project 'adf-gradle'.
dependencyInsight - Displays the insight into a specific dependency in root project 'adf-gradle'.
dependentComponents - Displays the dependent components of components in root project 'adf-gradle'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'adf-gradle'. [incubating]
projects - Displays the sub-projects of root project 'adf-gradle'.
properties - Displays the properties of root project 'adf-gradle'.
tasks - Displays the tasks runnable from root project 'adf-gradle'.

Oracle-adf tasks
----------------
assemble - Build ADF artficats
clean - Clean ADF workspace

To see all tasks and more detail, run gradlew tasks --all

To see more detail about a task, run gradlew help --task <task>

BUILD SUCCESSFUL

Total time: 0.944 secs

As you can see Oracle-adf task group appeared after standard Gradle tasks.

Let’s test assemble task. Run gradlew assemble command.

better-coding@bc-vbox:~/jdeveloper/mywork/ADFGradle/adf-gradle$ ./gradlew assemble
:clean
Cleaning project adf-gradle
:assemble
Assembled artifact com.bettercoding:adf-gradle-1.0-SNAPSHOT

BUILD SUCCESSFUL

Total time: 0.941 secs

As you can see both clean and assemble tasks fired in proper order.

 

Tasks implementation

Edit build.gradle file and define project external properties as below:

  • middlewareHome – this property will be passed from command line using -PmiddlewareHome=<MIDDLEWARE_HOME>
  • ojDeployExec – path to ojdeploy tool (linux version)
  • adfWorkspace – realitive path to your ADF workspace – in our case it’s parent directory.
  • adfWorkspaceDeployDir – relative path to ADF deploy directory. This is directory configured in application deployment profile as a target for EAR file.
  • gradleTargetDir – relative path to directory for final artefacts.
  • ojDeployBuildfile – relative path to ojdeploy-buildfile.xml you’ve already prepared.
  • ojDeployAppWorkspaceDir – absolute path to adfWorkspace.
group 'com.bettercoding'
version '1.0-SNAPSHOT'

ext {
    middlewareHome = project.hasProperty("middlewareHome") ? project.property("middlewareHome") : null
    ojDeployExec = middlewareHome + "/Oracle_Home/jdeveloper/jdev/bin/ojdeploy"
    adfWorkspace = ".."
    adfWorkspaceDeployDir = "${adfWorkspace}/deploy"
    gradleTargetDir = "./build"
    ojDeployBuildfile = "./ojdeploy-buildfile.xml"
    ojDeployAppWorkspaceDir = new File(adfWorkspace).getAbsolutePath()
}

...

 

Task: checkAdfEnvironment

Add another task checkAdfEnvironment responsible for checking if all environment variables, project external properties and other stuff are configured properly. The task will be called before both clean and assemble tasks. GradleException is thrown when middlewareHome project property is not specified.

...

task  checkAdfEnvironment {
    group "oracle-adf"
    description "Check if ADF environment configured correctly"
    doLast {
        if (project.ext.middlewareHome == null ) {
            throw new GradleException("Missing project property [middlewareHome]. " +
                    "Add -PmiddlewareHome=<MIDDLEWARE_HOME> switch to gradle invomation")
        }
    }
}

...

 

Task: clean

At first define order and dependency to checkAdfEnvironment task and then finish doLast section body to delete both adfWorkspaceDeployDir and adfWorkspaceDeployDir directories.

...

task clean {
    group "oracle-adf"
    description "Clean ADF workspace"
    mustRunAfter checkAdfEnvironment
    dependsOn checkAdfEnvironment
    doLast {
        println "Cleaning project ${project.name}"

        println "Deleting ${project.ext.adfWorkspaceDeployDir}"
        delete fileTree(project.ext.adfWorkspaceDeployDir)

        println "Deleting ${project.ext.gradleTargetDir}"
        delete fileTree(project.ext.gradleTargetDir)
    }
}

...

 

Task: assemble

As in previous task, define order and dependency to checkAdfEnvironment task.

In doLast section call exec task like below.

...

task assemble {
    group "oracle-adf"
    description "Build ADF artficats"
    mustRunAfter clean, checkAdfEnvironment
    dependsOn clean, checkAdfEnvironment
    doLast {
        println "Building using OJDeploy:"
        //Build
        exec {
            commandLine project.ext.ojDeployExec, '-buildfile', project.ext.ojDeployBuildfile, '-define', "app.workspace.dir=${project.ext.ojDeployAppWorkspaceDir}"
        }
    }
}

...

 

Collecting all together – Test

The final build.gradle file should now look like below.

group 'com.bettercoding'
version '1.0-SNAPSHOT'

ext {
    middlewareHome = project.hasProperty("middlewareHome") ? project.property("middlewareHome") : null
    ojDeployExec = middlewareHome + "/Oracle_Home/jdeveloper/jdev/bin/ojdeploy"
    adfWorkspace = ".."
    adfWorkspaceDeployDir = "${adfWorkspace}/deploy"
    gradleTargetDir = "./build"
    ojDeployBuildfile = "./ojdeploy-buildfile.xml"
    ojDeployAppWorkspaceDir = new File(adfWorkspace).getAbsolutePath()
}

task  checkAdfEnvironment {
    group "oracle-adf"
    description "Check if ADF environment configured correctly"
    doLast {
        if (project.ext.middlewareHome == null ) {
            throw new GradleException("Missing project property [middlewareHome]. " +
                    "Add -PmiddlewareHome=<MIDDLEWARE_HOME> switch to gradle invomation")
        }
    }
}

task clean {
    group "oracle-adf"
    description "Clean ADF workspace"
    mustRunAfter checkAdfEnvironment
    dependsOn checkAdfEnvironment
    doLast {
        println "Cleaning project ${project.name}"

        println "Deleting ${project.ext.adfWorkspaceDeployDir}"
        delete fileTree(project.ext.adfWorkspaceDeployDir)

        println "Deleting ${project.ext.gradleTargetDir}"
        delete fileTree(project.ext.gradleTargetDir)
    }
}

task assemble {
    group "oracle-adf"
    description "Build ADF artficats"
    mustRunAfter clean, checkAdfEnvironment
    dependsOn clean, checkAdfEnvironment
    doLast {
        println "Building using OJDeploy:"
        //Build
        exec {
            commandLine project.ext.ojDeployExec, '-buildfile', project.ext.ojDeployBuildfile, '-define', "app.workspace.dir=${project.ext.ojDeployAppWorkspaceDir}"
        }
    }
}

 

Lets run assemble task. Remember to pass path to MIDDLEWARE_HOME as a middlewareHome project property.

./gradlew assemble -PmiddlewareHome=/home/better-coding/tools/Oracle/Middleware_12.2.1.2.0
better-coding@bc-vbox:~/jdeveloper/mywork/ADFGradle/adf-gradle$ ./gradlew assemble -PmiddlewareHome=/home/better-coding/tools/Oracle/Middleware_12.2.1.2.0
:checkAdfEnvironment
:clean
Cleaning project adf-gradle
Deleting ../deploy
Deleting ./build
:assemble
Building using OJDeploy:

 Oracle JDeveloper Deploy 12.2.1.2.0
 Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.

----build file----
<?xml version = '1.0' standalone = 'yes'?>
<ojdeploy-build basedir=".">
   <defaults>
      <variable name="app.workspace.dir" value="/home/better-coding/jdeveloper/mywork/1/ADFGradle-integration-base/ADFGradle/adf-gradle/.."/>
   </defaults>
   <deploy command="deployToArchive">
      <parameter name="workspace" value="${app.workspace.dir}/ADFGradle.jws"/>
      <parameter name="profile" value="DockerDBTest_Project1_DockerDBTest"/>
   </deploy>
</ojdeploy-build>
------------------
Mar 01, 2018 12:30:18 AM oracle.security.jps.util.JpsUtil disableAudit
INFO: JpsUtil: isAuditDisabled set to true
[12:30:19 AM] ----  Deployment started.  ----
[12:30:19 AM] Target platform is  (Weblogic 12.x).
[12:30:19 AM] Running dependency analysis...
[12:30:19 AM] Building...
Compiling...
NFO: A default implementation of ADFConfig is being created for application. This can lead to unexpected results in some cases. Please add a basic META-INF/adf-config.xml to your classpath to avoid functional errors.
Writing task flow registry 'file:/home/better-coding/jdeveloper/mywork/ADFGradle/ViewController/classes/META-INF/task-flow-registry.xml'
[12:30:23 AM] Successful compilation: 0 errors, 0 warnings.
[12:30:23 AM] Build time 3,709 msec.
[12:30:23 AM] Deploying 2 profiles...
  file:/home/better-coding/jdeveloper/mywork/ADFGradle/ViewController/ViewController.jpr
Warning: oracle.xml.parser.v2.SAXParser: SAX property 'http://javax.xml.XMLConstants/property/accessExternalDTD' not recognized.
[12:30:24 AM] Wrote Web Application Module to file:/home/better-coding/jdeveloper/mywork/ADFGradle/ViewController/deploy/DockerDBTest_ViewController_webapp.war
  DockerDBTest_ViewController_webapp:ViewController.jpr
[12:30:25 AM] Wrote Enterprise Application Module to file:/home/better-coding/jdeveloper/mywork/ADFGradle/deploy/DockerDBTest_Project1_DockerDBTest.ear
[12:30:26 AM] Elapsed time for deployment:  7 seconds
[12:30:26 AM] ----  Deployment finished.  ----

BUILD SUCCESSFUL

Total time: 24.596 secs
better-coding@bc-vbox:~/jdeveloper/mywork/ADFGradle/adf-gradle$ 

 

Everything went perfect!

Here you can download final application.

 


What’s next?

Please leave me a comment what do you think about this tutorial and what do you want to read about in the next tutorial

If this tutorial was interesting to you can help me to reach a larger group of receivers by sharing this post.

Thank you!

 

10
Leave a Reply

avatar
7 Comment threads
3 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
4 Comment authors
lukasz.cieslaDerekPriyaAhmad Abutalib Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
trackback

[…] ADF and Gradle integration – part#1: Assembling ADF project using OJDeploy […]

Ahmad Abutalib
Guest
Ahmad Abutalib

For windows you must use: ojdeploy64.exe

Ahmad Abutalib
Guest
Ahmad Abutalib

Jenkins integration should be next

trackback

[…] Oracle ADF and Gradle integration – part#1: Assembling ADF project using OJDeploy […]

Priya
Guest
Priya

Hi,
Which Jdev version does this support. Can build an ADF application developed in jdev 11.1.1.7 ?

Regards,
Priya

trackback

[…] You can use your own application or just download sample application. If you use your own application remember to integrate it with Gradle  as I showed you in this post. […]

Derek
Guest
Derek

Will play a little devil’s advocate here. Though this article is great for demonstrating how to integrate gradle with an ADF-based project, I feel you are using gradle incorrectly and as a result nullifying all the benefits of gradle. For you to continue to rely on ojdeploy to build the project means you will not benefit from gradle’s incremental compiler, parallel executions, etc. This article is more of a POC just to say it can be done, but what is the point of this if you don’t gain anything from it? Think of it this way, suppose ojdeploy is a… Read more »

Close Menu