Developer Cloud Service: Continuous Integration with JDeveloper 12.2.1

The last blog showed that the Oracle Developer Cloud Service is now available for JDeveloper and ADF 12.2.1 (Developer Cloud Service with JDeveloper 12.2.1 available). The missing part is the connection of the DCS to the newly created JCS for version 12.2.1. This we show in the blog.

The ground work, how to set up a build system for the DCS has been shown in Fasten your seat belts: Flying the Oracle Development Cloud Service (3 – Take Off – ROTATE). We now have to find out which environment variable to use for the 12.2.1 installation. At the time I wrote the mentioned blog there where only environment variables for 11.1.1.7.1 and 12.1.3.0 available. Looking at the documentation Using Hudson Environment Variables we find that the variables

  • ORACLE_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1/jdeveloper
  • MIDDLEWARE_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1
  • WLS_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1/wlserver

Are the right ones (and the only ones which point to 12.2.1). In the application.properties file (from the ‘… Take Off…’ blog) we exchange

# Don't change anything below!
 oracle.home=${env.ORACLE_HOME_12C3}
oracle.commons=${env.MIDDLEWARE_HOME_12C3}/oracle_common
middleware.home=${env.MIDDLEWARE_HOME_12C3}
install.dir=${env.ORACLE_HOME_12C3} 

with

# Don't change anything below!
oracle.home=${env.ORACLE_HOME_SOA_12_2_1}
oracle.commons=${env.MIDDLEWARE_HOME_SOA_12_2_1}/oracle_common
middleware.home=${env.MIDDLEWARE_HOME_SOA_12_2_1}
install.dir=${env.ORACLE_HOME_SOA_12_2_1} 

This change will use the JDeveloper 12.2.1 to run ojdeploy and configure the application to run on a WebLogic Server 12.2.1. This should do the trick and we can use the DCS build system to create application using ADF 12.2.1. As the application I used for the ‘Fasten your seat belts…’ blog series was pretty simple I like to show the result using the application I used for a presentation at the DOAG DevCamp2016, named AppsClouUIKit. You can read all about this application in a blog I wrote here DOAG DevCamp2016.

The application was build using JDeveloper 11.1.1.9.0 and has been migrated during the DevCamp to 12.1.3. This was the DCS version which was available at the time of the DevCamp. The first task is to migrate the source to 12.2.1 by creating a new branch in the GIT repository for the new 12.2.1 version.

We Clone the repository and create a new branch 12_2_1 which we use to build the AppsCloudUIKit for 12.2.1. As we are now running JDeveloper 12.2.1 we can use the Team-Server to get the sources from the DCS GIT repository

But we can use any other GIT client to get it. As this is covers in other blogs I’ll skip the details here. In the end we have this branch tree

Where the green marked local branch 12_2_1 is the one we are working on.

After changing the application.properies as shown above we can run the build using ant on the local machine

By selecting the ‘deploy’ target.

The result is an EAR file in the deploy folder

Setting up the build job

Let’s check-in the changes and setup the build in the DCS. Here are the steps for the build job

With this we can build the application to get the result

Setting up the Deployment

The final task is to set up the deploy task to deploy the application on the JCS_12_2_1. When we select the ‘Deploy’ tab we see the existing deployment configuration for the 12.1.3 JCS.

For the JCS 12.2.1 we created a new JCS instance with a different IP (public). Before we can create a new configuration for the 12.2.1 JCS instance we have to allow the Hudson user access to the JCS. This process is described in detail at Deploying an Application from Oracle Developer Cloud Service to Oracle Java Cloud Service

It’s absolutely necessary to get the Oracle Developer Cloud Service SSH public key and add this key to the JSC 12.2.1 instance as authorized key. Please follow the instructions given in the link above to do so.

After this is done we can create a new deployment configuration

Start filling in the dialog by giving the configuration a name. Next we create a new ‘Deployment Target’

In the dialog fill in the public IP address from the new JC 12.2.1 and select SSH Tunnel. The user name and password is the one you selected when you created the JCD instance. Test the connection and close the dialog by clicking ‘Use Connection’

Finally we can complete the Deployment dialog

We choose ‘On Demand’ here which let us specify which job/Build and artifact to use. A click to ‘Save and Deploy’ closes the dialog and the artifact will be deployed to the JCS 12.2.1. The URL to open the application is AppsCloudUIKit 12.2.1

And we should see

Developer Cloud Service with JDeveloper 12.2.1 available

I almost missed that Developer Cloud Service has been updated to 12.2.1. Great news as we now can use JDeveloper 12.2.1 to access the agile capabilities like

  • Interact with Tasks/Issues in JDeveloper
  • Leverage the Team view in JDeveloper (tasks, builds, and code repositories)
  • Connect to DevCS and its projects from inside JDeveloper
  • Create Agile boards and manage sprints in Developer Cloud Service
  • Associate code commits with specific tasks
  • Monitor team activity in the Team Dashboard
  • Handle Git transactions

For more information about how JDeveloper and the DCS are integrated watch this video ‘Agile development with Oracle JDeveloper and Oracle Developer Cloud Service’.

This was possible since last year. So, what’s new?

New is that the JCS is also available in 12.2.1 and that we can use the whole continuous integration scenario. For this we have to configure a 12.2.1 JCS instance which then can be used for deployment. When we select to create a new instance of a JCS we see the new wizard which allows us to select a WebLogic Server 12c in version 12.2.1

On the ‘Edition’ page we don’t find anything new so we skip it and go to the Details page where we specify the needed information for the service, database configuration, backup and the WebLogic user

After getting the confirmation page we create the new service and finally after a short time we see the new service

A look at the Enterprise Manager of the new service shows the new login page

and after logging in the new 12.2.1 Enterprise Manager

It look modern and fresh. However, this is not what this blog is about. I installed my ADF Version Web Service BlogAdfVersionWS to check which ADF version is running in this instance. Selection the modules we find the test point on the right side of the Web Service

After selecting the test point we select to run the ‘GetVersion’ service

and get

That’s right what we expect when running ADF 12.2.1!

Next time we see how to change the build and deployment part of the DCS to work with the JCS 12.2.1.

Naviagting an af:table in pagination mode from a bean

A question on the JDeveloper and ADF OTN forum asked about how to navigate to a specific page of an af:table in pagination mode. As of JDeveloper 11.1.1.7.0 adf tables can be rendered in scroll mode or in pagination mode where only a specific number of rows are visible in the table.

af:table in pagination mode

To navigate the pages there is a small navigation toolbar below the table which allows to enter a page number or to navigate to the previous, next, first or last page.

The problem to solve is how to navigate the paginated table from within a java bean?

The table doesn’t offer any navigation listeners or methods you can bind bean methods to. Luckily there is the RangeChangeEvent one of the FacesEvents which can e used to notify a component that change in the range has taken place.

All we have to do to navigate the table in pagination mode is to calculate the needed parameters

  • oldStart: The previous start of this UIComponent’s selected range, inclusive
  • oldEnd: The previous end of this UIComponent’s selected range, exclusive
  • newStart: The new start of this UIComponent’s selected range, inclusive
  • newEnd: The new end of this UIComponent’s selected range, exclusive

We add an input field to the page which allow us to enter a page number and a button which we use to call an action listener in a bean.

The running application looks like

Running application

Another button is used to calculate the index of the selected row in the whole rowset, the index on the page and the page number. The row index and the index of the row on the page are zero based, page numbers start with 1. Let’s look at the code:

public void onGotoPage(ActionEvent actionEvent) {
BindingContainer bindingContainer = BindingContext.getCurrent().getCurrentBindingsEntry();
// get number of page to goto
AttributeBinding attr = (AttributeBinding) bindingContainer.getControlBinding("gotopage1");
Integer newPage = (Integer) attr.getInputValue();
if (newPage == null) {
return;
}
// page one starts at index 0 so subtract 1 from the pagen number
newPage--;
DCIteratorBinding iter = (DCIteratorBinding) bindingContainer.get("EmployeesView1Iterator");
// calculate the old and new rages for the RangeChangeEvent
int range = iter.getRangeSize(); // note both the table and we take the page size from the iterator's RangeSize
int oldStart = iter.getRangeStart();
int oldEnd = oldStart + range;
int newStart = newPage * range;
int newEnd = newStart + range;
// find the table
UIViewRoot iViewRoot = FacesContext.getCurrentInstance().getViewRoot();
UIComponent table = iViewRoot.findComponent("t1");
// build the event and fire it
RangeChangeEvent event = new RangeChangeEvent(table, oldStart, oldEnd, newStart, newEnd);
((RichTable)table).broadcast(event);
// update the table
AdfFacesContext.getCurrentInstance().addPartialTarget(table);
}

Line 2-8 we get the new page number we want to navigate to. Line 9-10 we subtract 1 from the given number as the page is zero based internally. In Line 11 we get the iterator which we need to get the range size and the start of the current range (lines 13-15). These values are oldStart and oldEnd. Lines 16-17 we calculate the new start range as page to go multiplied with the range. The newEnd parameter is the newStart pus the range size.
In lines 18-20 we get to the table component on the page. Then we create the RangeChangeEvent and broadcast the event to the table component in lines 21-23. Finally we ppr the table to see the change in the UI.

To show how to calculate the other way around, to get from the selected row in a table to the index on the page, the page number and the index in the rowset we added another button ‘GetPageOfSelectedRow’which calls a listener in the same bean which builds a string with the needed information.

public void onGetCurrentPage(ActionEvent actionEvent) {
BindingContainer bindingContainer = BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding iter = (DCIteratorBinding) bindingContainer.get("EmployeesView1Iterator");
// calculate index and page number. Index is zero based!
int currentRowIndex = iter.getRowSetIterator().getCurrentRowIndex();
_logger.info("CurrentRowIndex: " + currentRowIndex);
int currentPage = currentRowIndex / iter.getRangeSize();
currentPage++;
_logger.info("Current Page:" + currentPage);
int indexOnPage = (currentRowIndex % iter.getRangeSize());
_logger.info("Current index on Page:" + indexOnPage);
// get an ADF attributevalue from the ADF page definitions
AttributeBinding attr = (AttributeBinding) bindingContainer.getControlBinding("selectedRow1");
StringBuffer sb = new StringBuffer();
sb.append("row index overall: ");
sb.append(currentRowIndex);
sb.append(" row index on page: ");
sb.append(indexOnPage);
sb.append(" Page: ");
sb.append(currentPage);
attr.setInputValue(sb.toString());
}

To get the index of the selected row in the whole rowset we need the iterator and get the RowSetIterator from it. The rowSetIterator method getCurrentRowIndex() returns the index of the current row (line 5). The current page is calculated by dividing the current index through the range size (line 7). The final information is the index of the selected row on the page which is calculated as the current index modulo the range size (line 10). The rest of the listener build a string out of this information and writes it to a pageDef variable which is referenced in an outputfield on the page.

<af:outputText value="#{bindings.selectedRow1.inputValue}" id="ot8" partialTriggers="b2"/>

Here are some images from the sample application.

The sample application is build using JDev 12.1.3 and uses the HR DB schema. The sample can be downloaded from  Github

DOAG DevCamp 2016, Bonn, Germany

On 22nd and 23rd of February the DOAG 2016 DevCamp take place in Bonn, Germany. This annual developer conference is presented as a combination of a bar camp and hands-on sessions called ‘ADF Fittness Center’.

While the bar camp allows everybody to bring in ideas for sessions (45 minutes or less each) on every Oracle development theme (Forms, Apex, ADF, team development, …), the hands-on sessions have a main focus area.

This year the DevCamp hands-on sessions and workshops have their main focus on IoT, ADF (mobile, cloud) and new 12.2.1 features like JET.

The hands-on allows every attendee to try things out on their own device while experts from Oracle and the community help them to get going.

  • Marcel Amende, expert for middleware products, “SOA & Cloud” integration and IT-Infrastructures will talk about the ‘Internet of Things’ (IoT)
  • Frank Nimphius together with Jürgen Menge will cover Mobile and MAF and new features of JDev 12.2.1
  • ACE Director Andreas Koop together with Geertjan Wielenga and Hendrik Gossens will hold a hands-on session on Oracle Jet developing
  • ACE Director Timo Hahn shows how to use the Oracle Developer Cloud. In a hands-on session attendees can try out how to develop applications in the cloud using issue tracking and continuous integration

Most discussions and hands-on sessions are in German language.

The event is a great way to meet with peers and expert and discuss problems or share knowledge.

For more info visit DOAG 2016 DEVCAMP

 

The power of calculated fields in ADFbc

Lately I saw a couple of posts on the OTN JDev & ADF forum where users tried to add redundant data into their data model and store it to the DB table. One common use case here is to have the result of a calculation as an attribute of a table.

In general you should be very careful when doing this. This is error prone and will you get into trouble almost every time. If you do add an attribute for such a calculation to a table in the DB, you have to think of the integrity of the data. Let’s look into the use case and the integrity problem.

Use Case

We have a table in the DB which holds start and end for multiple data types like integer, data and timestamp:

Selection_719

We use the different start and end attributes to calculate the difference between start and end.

We do have the option to add attributes to the table and calculate the difference using a trigger in the DB each time the data is inserted or updated. Problem here is that the user will see the result only after the insert or update is done. For web pages this isn’t a good design.

Another option is to add the fields but do the calculation in the business component layer in ADFbc and store them in the DB together with all other changes done to the data. The your see the calculation, but other applications won’t see them until you store the record.

Problem with storing redundant data in a DB table

Both options have one flaw. When you store the result of a calculation in the DB, what happens if someone, person or program, changes one of the attributes used in the calculation?

Assume STARTINT is set to 5, ENDINT is set to 10. The result of the calculation is 5. This result we store in an attribute in the DB table. Now a bad programmer who does not know about the calculation, changes the ENDINT to 15 and commits the change.

When the other program looks at the data again the data is inconsistent. Which of the values is correct? The result? The STARTINT value? The ENDINT value? Or is the calculation simply wrong?

In this simple use case it’s fairly easy to find the problem. In more complex use cases where other workflows depend on the numbers it’s not as easy.

This leads to the solution shown in this post: don’t store results of calculations in the DB if possible. Do the calculation when they are  needed.

There are cases where storing the result would be the better way to archive the whole use case, but this has to be decided on the use case and weighted against the complications. Most simple use cases don’t need to store the results and should not.

The remainder of this post we see how to implement such calculated fields using ADFbc.

Implementing calculated fields in ADFbc using Groovy

We start with creating a new Fusion Web Application and building the ‘ADF Business Components from a Table’. The sql script to create the table is

CREATE TABLE "HR"."CALCULATION"
 ( "ID" NUMBER(*,0) NOT NULL ENABLE,
 "STARTINT" NUMBER(*,0),
 "ENDINT" NUMBER(*,0),
 "STARTTIME" DATE,
 "ENDTIME" DATE,
 "STARTTIMESTAMP" TIMESTAMP (6),
 "ENDTIMESTAMP" TIMESTAMP (6),
 CONSTRAINT "CALCULATION_PK" PRIMARY KEY ("ID")
 );
REM INSERTING into CALCULATION
 SET DEFINE OFF;
 Insert into CALCULATION (ID,STARTINT,ENDINT,STARTTIME,ENDTIME,STARTTIMESTAMP,ENDTIMESTAMP) values ('1','1',null,to_timestamp('24-DEZ-15','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('26-DEZ-15','DD-MON-RR HH.MI.SSXFF AM'),null,null);
 Insert into CALCULATION (ID,STARTINT,ENDINT,STARTTIME,ENDTIME,STARTTIMESTAMP,ENDTIMESTAMP) values ('2','4','6',to_timestamp('31-DEZ-15','DD-MON-RR HH.MI.SSXFF AM'),to_timestamp('05-JAN-16','DD-MON-RR HH.MI.SSXFF AM'),null,null);

We use the HR DB schema to add the table, but it can be added to any schema you want. The CALCULATION table consists of some start and end values of different types to later show how to work with them. To work with the table we add two records resulting in the following data

Selection_720.jpg

I don’t show the steps to create the basic application from the wizards as the application is available via the link GitHub base application.

Once you downloaded and unzipped the workspace you should see the base application as it will be created by following the wizard.

Selection_721

The first step is to create a transient field in the Calculation EO to hold the result of the calculation of the difference of STARTINT and ENDINT. The difference here  is, that we store the result in the EO as transient attribute which is not stored into the DB.

The real work is shown in the third image above ‘edit expression…’. Here we enter a Groovy expression to calculate the difference between STARTINT and ENDINT as

if (Endint == null) 
  {return 0} 
else 
  {return Endint-Startint}

The Groovy expression uses the attribute names from the EO not the ones from the DB table. First we check if the Endint is given, if not we return 0. If there is an Endint we return the (Endint-Startint).

We then add notifications to the calculated attribute whenever the attributes Startint or Endint change to recalculate the Durationint attribute (lower half of the dialog). Next we set the AutoSubmit  property of the Startint and Endint attributes to true to make sure we get the new values when we calculate the result.

Finally we add the new calculated attribute to the VO. We can now test the application module using the application module tester:

We now add a index page to the View Controller project to add an UI to the application. We can just drag the CalculationView1 and drop is as an ADFForm with navigation and submit onto the page.

In the resulting form we set the Startint and Endint fields to autosubmit=’true’ to make sure the new values are submitted. As the Durationint field isn’t updateble we set it to read only.

Running the application will show you

The application in this state can be downloaded from GitHub (feature/calculated_int_field).

To show that this can be done with other data types we can use the other attributes of the table. As the way to do this is the same I spare to give detailed instructions. You can download the final application from GitHub (final).

All samples yre using the HR DB schema and table called CALCULATION. The needed SQL code to create the table and to insert data to the table is posted in here.

JDev 12.2.1: Remote Task Flows in Action

The new JDeveloper version 12.2.1 is just out and has a lot of new features to investigate. In this post we see how remote task flows work. Yes, they are finally here and they are working. At least if you install a patch available from support.oracle.com.
The downloadable version on JDev 12.2.1 has a small bug which prevents you from running remote task flows (refer to https://community.oracle.com/thread/3816032). Support and the dev team quickly delivered a patch for this. To get the patch, open a service request and ask for a patch for bug 22132843.

Let’s start. We need two applications to show how remote task flows are implmented. One is the remote task flow producer, one consumes the remote task flow. An application can be both, producer and consumer. For this sample we keep it simple and define one app as producer and one as consumer.

Producer Application
This application is really simple as it consists of only one page and one task flow which shows the departments and its employees of the HR DB schema.

Remote Task Flow Producer Application

Remote Task Flow Producer Application

The image above shows the running application stand alone. The single page has the header and a simple task flow beneath it to show the departments and their employees.


There are two properties to set in the task flow.
1) in must be remote invocable
2) the transaction must be isolated

Next we have to make the application aware that it should be a remote task flow producer. For this we edit the projects properties and select the ‘ADF Task Flow’ node.

Project Properties for Producer Application

Project Properties for Producer Application


Please note is the second checkbox selected which allows anonymous users to access the remote task flow. This should not be used in a production environment as this would allow anybody to access the task flow. The doc shows how to secure the access to a remote task flow (see link below).

These settings will add a special servlet and a servlet filter to the web.xml file of the application.

There are more things to consider which you find in the docs at How to Configure an Application to Render Remote Regions

That’s it for the simple producer application.

Consumer Application
The second application is simple too. Here we use a single page which again uses the HR DB schema to show the departments as an editable table in a panel splitter. On the right of this we show the remote task flow of the producer application.

Consumer Application

Consumer Application


In the image above the remote task flow isn’t visible as it is not added at the moment.
To make the remote task flow available we need to run the producer application. Here we have to be careful if we try this out using the embedded WebLogic Server. As only one application can be started in debug mode, we need to start the producer application as a normal application.
Run Producer Application

Run Producer Application

In the consumer application we set the project properties for the ADF Task Flow to allow it to consume remote task flows

Consumer Application Project Properties

Consumer Application Project Properties

Now we create a remote task flow connection. Open the resource palette and select to create a ‘Remote Region Producer…’ from the IDE connections.
Here we fill in the needed info like the path to the remote producer servlet which will get us the names of all remote task flows the application holds. To access the remote task flow we define the URL endpoint


The details about what to fill in are again from the doc.

In the consumer application we now open the one page and drag the remote task flow from the ressource palette onto the page and drop it in the right hand splitter

Drop Remote Region in Consumer Application

Drop Remote Region in Consumer Application


This will give us the known image in design mode as if you use a normal region
Consumer Page

Consumer Page


We are ready to run the consumer application and get
Running Consumer Application

Running Consumer Application

Nice!

You can download the sample application from GitHub:
Consumer Application
Producer Application
Both application use the HR DB schema. Make sure to adjust the DB connection to point to your db server.

The Oracle Database Developer Choice Awards – Time to Vote!

It’s time to give something back to all the experts helping us with our problems in SQL, PL/SQL, APEX, ORDS, DB Design their with deep expertise. Show your appreciation by voting for your favorite expert.

Andy Mendelsohn, who runs the Database Server Technologies group at Oracle, and has been deeply involved in Oracle Database for decades, has established a new awards program to honor and give more visibility to members of the community who combine technical excellence with a commitment to sharing their know-how with developers.

The Oracle Database Developer Choice Awards

This is a different kind of awards program for Oracle; it’s called “Developer Choice” because with these awards, our users nominate people and ACE judges come up with a list of finalists. Thirty-two finalists have been selected in five categories: SQL, PL/SQL, Application Express, ORDS and Database Design.

Now it’s time for everyone in the community determine the winners by voting at the Oracle Technology Network: https://community.oracle.com/community/database/awards.
Voting closes 15 October. Winners will be announced at the YesSQL celebration at Oracle Open World 2015 on 27 October.

Fasten your seat belts: Flying the Oracle Development Cloud Service (4 – In Flight 1)

In the last part of the series Fasten your seat belts: Flying the Oracle Development Cloud Service (3 – Take Off – ROTATE) we finished the work on the first cloud workspace, a utility project holding framework extension classes we use in the upcoming development. We created a branch to add the build system we can use in the cloud as well as on the developer’s machine.
The developer checked in all his/her changes, but did not merge the branch back into the mainline development (master). This part describes how this action, called a merge request, is done. This action can be used as a quality gate to review the code the developer has build.
After logging into the Oracle Developer Cloud as developer we select the ‘Merge Requests’ tab of the project

Merge Requests

Merge Requests


where we create a new request by clicking on the ‘New Request’ button. In the next dialog we fill in the needed data
Create Merge Request dialog

Create Merge Request dialog


The target branch is the branch we like the feature branch to be merged into, in our case it’s the branch called ‘master’. If you have other branches you like to merge you can do this too and later merge the whole merged feature branches back into the master branch. The ‘review Branch’ is the branch we want the review on, in our case the ‘feature-setup-build’ branch. In the ‘reviews’ field we must add at at least one member of the team, but can add multiple members if we like. Each of the reviewers then gets a notification via e-mail that a review is waiting.

The developer can only wait now for the action of the reviewers. Sure he can do something else like start another task for the project:)

The mails give some basic information about the request and the links to quickly access the cloud. After logging into the Cloud as reviewer the same ‘Merge Requests’ looks like

As we see, there now are the ‘Approve’ and ‘Reject’ buttons available for the Reviewer.
The reviewer should look at the changes made in the branch e.g. by looking at the commits for it.
Commits of the feature branch

Commits of the feature branch


As we don’t know what these files are doing, we reject the merge request

This will notify the developer who can and should act on the comment.

In this case the files are obsolete and can be deleted from the feature branch before merging (by the developer).

After changing the merge request by adding a hint that we delete the obsolete files, the reviewer again get some e-mails notifying him about this change.
Looking at the request after login, the reviewer approves the request and merges the branch into the master branch.

If we now look at the master branch we see the build files as part of the master branch.

One final thing to do is to switch the build system configuration from the feature branch to the master branch. When we started working on the feature we set up the build system to use the feature-setup-build branch. We now switch the build setup to use hte master branch.

This concludes this part of the series. Next we build a simple ‘normal’ ADF application in the cloud, applying what we have learned so far.

Fasten your seat belts: Flying the Oracle Development Cloud Service (3 – Take Off – ROTATE)

The last part of the series 3 – Take Off – V1 we finished when we could build hte application using ANT on the local machine. In this part we are going to try this on the Oracle Developer Cloud. Finally we should see how Continuous Integration and Continuous Delivery works in the cloud.

Alt NOTE
I created a fresh set of ANT build scripts named ‘buildlocal.xml’ and ‘buildlocal.properties’ from the project to demonstrate the process. The original ones name ‘build.xml’ and ‘build.properties’ are the final result which I didn’t want to revert. So when you create the ANT scripts yourself you can user the default names ‘build.xml’ and ‘build.properties’. When I talk about build files I now mean the ones named ‘buildlocal.*’.

Demo Build Files

Demo Build Files


For the same reason we create a new build job in the cloud names ADFTestBuild to show the steps to take. The final build job is named ADFCommunuityFrkExt.
Demo Build Job

Demo Build Job

We pushed the files local build files already to the remote repository. Let’s run the build on the could. First we log into the Oracle Developer Cloud as team member and switch to the build tab and create a new build job (ADFTestBuild)


Note that we use JDK 7 to build the project. The Oracle Developer Cloud offers JDK 6-8 to work with. As we use JDev 12.1.3 we use JDK 7
JDK's available

JDK’s available


In the Source Code Management section we select the repository and branch to use for this job. The advanced section can be left blank as it’s filled by the system when you save the job. There are more advanced option you can set but they are not part of this post. All we nach to remember

Alt NOTE
Builds are dependent on ONE branch

Alt NOTE
The Build Trigger defines that each minute the CI system checks the SCM if something has changed. If yes, it schedules to execute the build job.

When we are finished with the feature we have to change the build job or to create a new one which uses the master or default branch to build on. In our situation where we implement the CI we set the branch to the one we are working on named ‘feature-setup-build’.

After saving the new job we can start it by clicking on the ‘Run Now’ button


Hm, the build did not work as it did on the local machine. This is shown by the icon in the first column of the job history table. To find out what went wrong we look at the output of the build by clicking on the ‘console’ button in the last column of hte table
Build output

Build output


In the first marked section we see the build file ‘buildlocal.xml’ which was used and in the second marked section the error message. It looks liek the build job can’t find the task ‘OJDeployAntTask’. A look into the buildlocal.xml file at line 40 reveals

   <taskdef name="ojdeploy" classname="oracle.jdeveloper.deploy.ant.OJDeployAntTask" uri="oraclelib:OJDeployAntTask"
             classpath="${oracle.jdeveloper.ant.library}"/>

where line 40 is the classpath in the above listing. This means that the variable “${oracle.jdeveloper.ant.library}” is not found. A look into the Oracle Developer Cloud at Developing Oracle ADF Applications with Oracle Developer Cloud Service give the needed information. We have to alter the build files
1. add a line

<property environment="env"/>

to the build.xml file before loading the build.properties
2. change the build.properties file to use information from the now loaded environemnt
The second part is a bit confusing. From the link above we learn to set a variable as
oracle.home=${env.ORACLE_HOME}
which is misleading a bit. The problem is that the developer cloud offers two environments to the user. One for 11g and one for 12c. As we use the one for 12c we have to use a different setup which can be found in the docs too at a different location Using Hudson Environment Variables. The second link tells us to use
oracle.home=${env.ORACLE_HOME12C3}

Alt NOTE
Add property environment="env" to your build.xml to load the environment of the server
Alt NOTE
Add
oracle.home=${env.ORACLE_HOME_12C3}
oracle.commons=${env.MIDDLEWARE_HOME_12C3}/oracle_common
middleware.home=${env.MIDDLEWARE_HOME_12C3}
install.dir=${env.ORACLE_HOME_12C3}
to the build.properties file to make use of hte servers environment.

With this info we can make the needed changes. The resulting build.properties is

#Fri Jul 24 15:06:08 CEST 2015
#Change the next three properties to match your projects names
workspace.name=ADFCommunityFrkExt
workspace=${env.WORKSPACE}
project.viewcontroller.name=FrkExtModel
project.deploy.folder=deploy
oracle.jdeveloper.deploy.profile.name=adflibADFCommunityFrkExt
output.dir=classes

# Don't change anything below!
oracle.home=${env.ORACLE_HOME_12C3}
oracle.commons=${env.MIDDLEWARE_HOME_12C3}/oracle_common
middleware.home=${env.MIDDLEWARE_HOME_12C3}
install.dir=${env.ORACLE_HOME_12C3}

#Flags
javac.deprecation=off
javac.nowarn=off
java.debug=on

project.workspace.file=${workspace.name}.jws
oracle.jdeveloper.ant.library=${oracle.home}/jdev/lib/ant-jdeveloper.jar
oracle.jdeveloper.workspace.path=${workspace}/${workspace.name}.jws
oracle.jdeveloper.project.name=${project.viewcontroller.name}
oracle.jdeveloper.deploy.dir=${workspace}/${project.deploy.folder}
oracle.jdeveloper.ojdeploy.path=${env.ORACLE_HOME_12C3}/jdev/bin/ojdeploy${env.EXEC_SUFFIX}
oracle.jdeveloper.deploy.outputfile=${workspace}/${project.deploy.folder}/${oracle.jdeveloper.deploy.profile.name}

and the build.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!--Ant buildfile generated by Oracle JDeveloper-->
<!--Generated Aug 22, 2015 3:15:37 PM-->
<project xmlns="antlib:org.apache.tools.ant" name="FrkExtModel" default="all" basedir=".">
  <property environment="env"/>
  <property file="build.properties"/>
  <path id="library.ADF.Model.Runtime">
    <pathelement location="${oracle.commons}/modules/oracle.idm_12.1.3/identitystore.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.model_12.1.3/adfm.jar"/>
    <pathelement location="${oracle.commons}/modules/groovy-all-2.1.6.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.model_12.1.3/adftransactionsdt.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.view_12.1.3/adf-dt-at-rt.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.model_12.1.3/adfdt_common.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.model_12.1.3/adflibrary.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.xdk_12.1.3/xmlparserv2.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.model_12.1.3/db-ca.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.model_12.1.3/jdev-cm.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.ldap_12.1.3/ojmisc.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.share_12.1.3/commons-el.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.share_12.1.3/jsp-el-api.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.share_12.1.3/oracle-el.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.security_12.1.3/adf-share-security.jar"/>
    <pathelement location="${oracle.commons}/modules/oracle.adf.security_12.1.3/adf-controller-security.jar"/>
    <pathelement location="${oracle.commons}/modules/javax.mail_2.0.0.0_1-4-4.jar"/>
  </path>
  <path id="classpath">
    <path refid="library.ADF.Model.Runtime"/>
  </path>
  <target name="init">
    <tstamp/>
    <mkdir dir="${output.dir}"/>
  </target>
  <target name="info">
    <echo level="info">build: env.ORACLE_HOME=${env.ORACLE_HOME_12C3}</echo>
    <echo level="info">build: env.WORKSPACE=${env.WORKSPACE}</echo>
    <echo level="info">build: workspace=${workspace}</echo>
    <echo level="info">build: install.dir=${env.ORACLE_HOME_12C3}</echo>
    <echo level="info">build: oracle.commons=${oracle.commons}</echo>
    <echo level="info">build: oracle.jdeveloper.ant.library=${oracle.jdeveloper.ant.library}</echo>
    <echo level="info">build: oracle.jdeveloper.ojdeploy.path=${oracle.jdeveloper.ojdeploy.path}</echo>
    <echo level="info">build: oracle.jdeveloper.deploy.dir=${oracle.jdeveloper.deploy.dir}</echo>
    <echo level="info">build: oracle.jdeveloper.deploy.profile.name=${oracle.jdeveloper.deploy.profile.name}</echo>
    <echo level="info">build: oracle.jdeveloper.workspace.path=${oracle.jdeveloper.workspace.path}</echo>
    <echo level="info">build: oracle.jdeveloper.deploy.outputfile=${oracle.jdeveloper.deploy.outputfile}</echo>
  </target>
  <target name="all" description="Build the project" depends="info,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">
    <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="false"/>
        <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="UTF8" source="1.7" target="1.7" includeantruntime="false">
      <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="**/*.JPEG"/>
      <include name="**/*.JPG"/>
      <include name="**/*.PNG"/>
      <include name="**/*.cpx"/>
      <include name="**/*.dcx"/>
      <include name="**/*.ejx"/>
      <include name="**/*.gif"/>
      <include name="**/*.ini"/>
      <include name="**/*.jpeg"/>
      <include name="**/*.jpg"/>
      <include name="**/*.png"/>
      <include name="**/*.properties"/>
      <include name="**/*.sva"/>
      <include name="**/*.tag"/>
      <include name="**/*.tld"/>
      <include name="**/*.wsdl"/>
      <include name="**/*.xcfg"/>
      <include name="**/*.xlf"/>
      <include name="**/*.xml"/>
      <include name="**/*.xsd"/>
      <include name="**/*.xsl"/>
      <exclude name="build.xml"/>
    </patternset>
    <copy todir="${output.dir}">
      <fileset dir="src">
        <patternset refid="copy.patterns"/>
      </fileset>
      <fileset dir=".">
        <patternset refid="copy.patterns"/>
      </fileset>
    </copy>
  </target>
</project>

The files above are the original ones and can be run from the build console to get this

Great, we now have successfully enabled CI in the cloud for the ‘Framework Extension’ project. Well, there is something more to think about. Can’t we use the same ANT build scripts on the local machine too?

Yes, we can but we have to make some adjustments for this.

Now that we read the environment from the server the ANT script is running on to set the some of the variables we need to set these environment variables on the local machine too. this can be done easily by altering the jdev start file (Linux) or using a batch to first set the environment variables and then start jdev (Windows). Below is my changes jdev start script

#!/bin/bash

#=============================================================================
#  Launcher for Oracle JDeveloper 12c (12.1.2.0.0)
#=============================================================================

unset -v GNOME_DESKTOP_SESSION_ID
export MIDDLEWARE_HOME_12C3=/opt/jdev/12.1.3.0.0/Oracle/Middleware
export ORACLE_HOME_12C3=/opt/jdev/12.1.3.0.0/Oracle/Middleware/Oracle_Home/jdeveloper
export WORKSPACE=/data/development/ENTW_12.1.3.0.0
export EXEC_SUFFIX=
/opt/jdev/12.1.3.0.0/Oracle/Middleware/Oracle_Home/jdeveloper/jdev/bin/jdev $1

As you see I set the environment variables which are later read through the build.xml file before starting jdeveloper.
The one line
export EXEC_SUFFIX=
need special attention. It’s only necessary if you run JDev using different operating systems (Linux and Windows). The build file has one variable pointing to the the ojdeploy executable
oracle.jdeveloper.ojdeploy.path=${env.ORACLE_HOME_12C3}/jdev/bin/ojdeploy${env.EXEC_SUFFIX}
Users using Windows need to add the suffix ‘.exe’ to this variable as ojdeploy can’t be started otherwise under Windows.
The problem is that we can’t add it for Linux systems as they don’t know this suffix. The solution I found is to add ${env.EXEC_SUFFIX} to the executable and set it to an empty string for Linux systems. For Windows systems you have to set this environment variable to ‘.exe’. For this I use a batch file where I use
~~~setx EXEC_SUFFIX .exe~~~
before starting JDev. In the same batch I set the other variables too

setx ORACLE_HOME_12C3 r:\Java\12.1.3.0.0\Oracle\Middleware\jdeveloper
setx MIDDLEWARE_HOME_12C3 r:\Java\12.1.3.0.0\Oracle\Middleware
setx EXEC_SUFFIX .exe

Alt NOTE
To make the build files work under Windows and Linux and iOS add an environment variable defining the suffix for executable files.

One final trick is to set the workspace directory. The build.properties file has one more environment variable workspace=${env.WORKSPACE} which we need to set.
As the workspace isn’t fix on a local machine, at least if you have more than one workspace, you can’t set this variable before you start JDev. This has to be done per workspace, when you change the workspace.
JDev has a solution for this in the ANT properties section

ANT Project Properties

ANT Project Properties


You can shoose from different variables JDev sets according to the workspace and project you are working with.
JDeveloper Variables

JDeveloper Variables

Alt NOTE
Set the env.WORKSPACE environment variable in the ANT properties of the project.

This concludes this part of the series. In the next post we finish the feature ‘feature-setup-build’ by introducing the code review function of the Oracle Developer Cloud. This will be followed by a post about building a simple ADF application with a UI which you use to show the Continuous Delivery (CD) option of the Oracle Developer Cloud.

Fasten your seat belts: Flying the Oracle Development Cloud Service (3 – Take Off – V1)

In part three of the series about the Oracle Developer Cloud we start working on a project as a member of a team in the developer cloud.

Before starting a new project some basic ground has to be covered. What architecture and technology should the project use as well as which package path to use. For the technology the the decision is easy as we want to use ADF. For the architecture we can choose on one of the patterns outlined at ‘Angles in the architecture’.

A good starting point is to introduce a for every ADF project, regardless of the architectural pattern, is a framework extension project (see ‘Extending a Helping Hand’). So we start with this too.

As a developer can’t create a new repository in a cloud project, we have to do this as a user with admin rights.


The first thing to note is that you should create an empty repository (unmark the ‘Initialize repository with README file’). If you initialize the repository with a README file, the developer can’t later just push his initial local version of the JDev workspace into the remote repository. The local repository has be updated with the README file first.

Now that the remote, empty repository exists we switch roles and work as a developer. For this we use a different login as a user who only has developer rights in the Oracle Developer Cloud.
Before the developer uses the new repository he creates a new workspace or project. We create a workspace for the framework extension library.


Next we add the ‘ADF Model Runtime’ library to the project and then the framework extension classes to the workspace.

Right now we don’t need to add or change any of the code in the created classes. If we later need to add some global functionality we come back to these classes. The next thing to do is to create an ADF library from the created classes

To make the new library available for other projects you can create a new file system connection using the same path we specified in the deployment descriptor

Later we come back to this step as we see that we have to change it a bit to make it work in the cloud. Right now we leaf it as is as this shows how you normally would do this in a normal project.
The next thing to do is to initialize a local GIT repository and push this to the Oracle Development Cloud repository as the initial master

and then push the local master branch to the Oracle Developer Cloud repository. For this we use the repository URL we get when we log into the cloud as the developer
Copy git repository address

Copy git repository address


Using this URL we push the local repository to the remote one

to finally see the changes in the cloud

More Decisions
With the basics covered we have to make another decision:
How to define the workflow for changes to make to the project sources.
Should all team members work on the trunk (called the mainline) or should each member use a branch to work on (called a feature branch). Both of these practices have their supporters and naturally opponents. The first is more CI like per definition. Feature Branches on the other side are not CI by the definition, as the code is not continuously integrated into the main line. This dispute is not for this post and may be not for this blog. Anyway, lets start with feature branching.
This allows us to show a feature of the Oracle Developer Cloud as it allows for code reviews which are mostly used if you work with feature branches, but can be used for the other practice too.

Feature: add build files
The feature we implement is to setup a build system for our framework extension project. We name the feature ‘feature-setup-build’


We learned in part 1 that the Oracle Developer Cloud provides a Continuous Integration server (CI). We plan to use this CI server to build our library whenever the code changes. For this we need to use ANT or Maven as the build system. For this project we choose ANT and can now build the needed build.xml files from the project

To finish this part we add the new files to our local repository and then push them to the remote as a new branch.

We push the local changes to the remote repository in the cloud using the same branch name

We had not looked into the created build.xml file or the build.properties files, we had them just created and pushed them into the repository. Question is, will they work?
Let’s try it on the local machine first.

Now we can run the ANT target ‘all’ which is the default one.
Well, as JDev 12.1.3 has somehow eliminated the ANT tool bar buttons running ANT on a project is a bit cumbersome (hopefully the ANT build buttons are back with the next release)

OK, this works like a charm.

As this post is already very long, we split the take off into two parts, V1 and ROTATE. This concludes part V1. Next time we make the necessary changes to the build files to integrate them to the clouds build system and start the CI process.

Note: for those who wonder about the terms V1 and ROTATE:
– V1 is the maximum speed at which an aircraft pilot may abort a takeoff without causing a runway overrun
– ROTATE or Vr is the speed of an aircraft at which the pilot initiates rotation to obtain the scheduled takeoff performance