Wednesday, 10 February 2010

XML Merge showing automatically resolved in JDeveloper

Some times when you update your Subversion working copy in JDeveloper a conflict will be detected in an xml file, such as the adfc_config.xml file for instance, but when you open the conflicted file in the resolve conflicts editor you get a perky dialog saying 'No unresolved conflicts'

This is because Subversion uses a basic line based compare which cannot resolve some simple xml changes, such as adding a couple of attributes to a tag, because that is seen as a line change so the Subversion server marks it as in conflict. Whereas JDeveloper has an XML aware compare tool that see this as a trivial xml change and automatically resolves it for you and returns the 'No unresolved conflicts' message.

See, we are helpful, except for perhaps the wording of that message...

More Hudson

Completely missed showing the successful output of the Hudson build from the last post. Actually it wasn't successful, the profile that generated the EAR wasn't a valid web archive because I'd failed to add the WAR file generated by the view controller project, so the first couple of runs failed until I twigged what was going on.

While I'm posting a picture of that, I might as well show off the excellent 'Changes' page in Hudson that shows what's been happening in source control to trigger build events. I've generated a few simple changes in my HRApp application, by committing a simple change on the trunk, and merging a simple change into the trunk from a branch for you to see below.

Monday, 8 February 2010

Ultra quick Hudson setup to build a JDeveloper ADF application

At the UKOUG conference in 2008 I said that you could use cron, or windows scheduler, to schedule builds and tests, but this last year, at the same conference, I said that using cron to schedule builds and test runs really wasn't acceptable any more.

During a peer review of that presentation a colleague asked me why I'd changed my opinion in the last year, and I gave the ease of use, and ease of install, of Hudson as my answer. I may even have said that it was quicker than using cron, my bluff was called and my colleague asked for a demo as his team were still using cron to do all their test runs. Happily his team have now moved their infrastructure to Hudson so I'm assuming the demo went well.

Here is pretty much the demo I gave to him which shows :-

  1. Installing Hudson
  2. Configuring Hudson to have the right plugins
  3. Creating a new headless node to run builds
  4. Creating a new job that checked out and built a simple ADF application using OJDEPLOY

Installing Hudson

Download the latest and greatest hudson.war file from and save it to a sensible directory here I've chosen C:\hudson

I've also created a 'home' directory under the 'hudson' directory and set the HUDSON_HOME environment variable to that directory. This will tell hudson to store it's data and plugins into this directory. Since we know where it is it makes it easier later on to back this directory up. So we haver things prepared lets start Hudson using a unused port, 8989, in this example by passing the --httpPort=8765 argument when starting Hudson. As long as you have a version of Java greater than 1.5 setup the following will work.

Obviously redirecting the output of this command to a log would make more sense see the Hudson wiki for more details.

Configuring Hudson to have the right plugins

If you connect to the port you specified on your machine you'll see Hudson is now running

If you click on 'Manage Hudson' -> 'Manage Plugins' and pick the 'Installed' tab you can see we've already got some of the most popular plugins.
Note :- If your behind a proxy, as I am, the proxy setup is on the 'Advanced' tab on this page. You can then download any extra plugins you want, since we only need subversion for this quick example we'll just move on.

Creating a new headless node to run builds

Since one of the key features of Hudson is its ability to add extra nodes to spread the load of building and testing lets create a headless node that can build ADF applications.

If we head back to the 'Manage Hudson' page and click 'Manage Nodes' you can see we only have a 'Master' node, click the 'New Node' Link and we can start creating a new node.

I've given it a name that describes it's properties, i.e. that it won't have a display so it's 'headless', it's for build adf apps 'adf-build', and it's the first of it's kind so '1'. Now lets describe the node in full.

Since we want to build using OJDEPLOY lets tell Hudson where it is located on the node by creating a environment variable that points to it. OJDEPLOY is located in the jdeveloper\jdev\bin directory under the ORACLE_HOME in which you installed JDeveloper.

Save the node to register it with Hudson.

You can see that the node appears with a red cross as it isn't up and running. If you click on the node the information on how to start the slave is displayed. So lets copy the line displayed for launching a headless node, by downloading the slave.jar, which is a link in the text, and running the command.

Creating a new job that checks out and builds a simple ADF application using OJDEPLOY

Return to the Hudson homepage and click 'New Job'. Give the job a sensible name, since I'm building an HRApp, there had to be one this is related to Oracle, I'll mention that in the name, I'll also note that I'm building the trunk out of the Subversion repository. Finally the it will be a free style software project were building.

Enter a description for the job. Set a number of days to keep the build results, this is essentially to stop Hudson from becoming full of old archive data. Then tie the job to the headless node using the tag 'headless'.

Lets configure the source control portion next. I've pointed it to the URL I want to build, supplied credential information when prompted, and to keep this simple I'm going to checkout a clean copy of the Application each time and not use update.

We need to tell Hudson to Poll SCM every minute to see if the HEAD revision has changed, this is a quick operation under Subversion. We then describe the action to run when the build is triggered. I've just used a windows batch command here, although I usually use a shell as I spend most of my days developing on Linux

Here is the batch script in full, it removes any previous ear artifact, runs ojdeploy on the Application in the checked out working copy, copies the ear file to the root of the Hudson workspace, and removes the working copy.
del *.ear
%OJDEPLOY% -profile dgfud-app -workspace %WORKSPACE%\DGFUD\DGFUD-HRApp.jws
copy %WORKSPACE%\DGFUD\deploy\*.ear %WORKSPACE%

I moved the .ear file generated to the root of the Hudson workspace so that we can archive it here.

A build will start immediately the job is saved as the trunk will always appear 'new' to Hudson the first time it looks. Wow, that was an epic description of a simple process. For further reading try Hudson Best Practices.

Wednesday, 23 December 2009

UKOUG '09 ADF Lifecycle Presentation

I've uploaded the slide presentation I gave at the UKOUG 2009 on a practical development lifecycle for Oracle ADF, i.e. how to build and test it.

Hopefully there are some useful nuggets in here, although the presentation also contained a fair amount of demos. I'll try and go through some of those simple examples here over the next couple of weeks.

Tuesday, 22 December 2009

Recovering lost files in JDeveloper

There is nothing more frustrating than losing a file that stops your application compiling.

Luckily it doesn't happen often these days with source control systems such as Subversion being both freely available, and free to use, but there are still times this occurs so I thought it was worth documenting here how you can reconstruct the missing file using JDeveloper.

Although it's documented in JDeveloper's Tip of the Day, it's surprising how few people remember that Restore from Local History is there when they really need it.

So here is a simple Java app in JDeveloper and I'm going to forcibly lose a file, in this case

Let's delete the file from the disk, to simulate an accidental removal.

And now lets get it back, by invoking Restore from Local History on the owning package.

Select the file that was lost.

Back to where we started with an application that compiles properly again. Hurrah!

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.