Troubleshooting headless Ant builds with Rational Application Developer

This article describes common pitfalls when using the headless Ant feature with WebSphere Studio Application Developer or Rational Application Developer. ("Headless" means running builds from the command line without using the WebSphere Studio or Rational Application Developer GUI.)  The headless Ant feature lets you run a series of unattended tasks, such as build and deploy.

Share:

Robert Weisz (weisz@ca.ibm.com), Team lead, WebSphere Studio Support, IBM Canada

Author photoRobert Weisz works with the WebSphere Studio/Rational Application Developer Technical Support team at the IBM Toronto Lab.



27 April 2005

Customizing runAnt.bat

As described in the IBM® WebSphere® Studio Application Developer online help, a sample batch file named runAnt.bat is included with the product to help you invoke the headless Ant feature. In WebSphere Studio Application Developer V5.1.2, runAnt.bat is found in:
$WSADinstallation\wstools\eclipse\plugins\com.ibm.etools.j2ee.ant_5.1.2,
while in IBM Rational® Application Developer V6, runAnt.bat is found in:
$RADInstallation\rwd\eclipse\plugins\com.ibm.etools.j2ee.ant_6.0.0.

In this article, WebSphere Studio Application Developer and Rational Application Developer are referred to collectively as "Application Developer." Readers should have some familiarity with Application Developer, including running builds and using the the Ant build script from inside the Application Developer GUI.

runAnt.bat (in Application Developer V5.1.2 as of interim Fix 006)
@echo off
setlocal
REM RUNANT_DIR=This directory (which may, or may not, be your current working directory)
set RUNANT_DIR=%~dp0

:studio
REM The root directory of your Studio installation
set STUDIO_DIR=%RUNANT_DIR%..\..\..\..
if not exist "%STUDIO_DIR%"\eclipse\jre  set STUDIO_DIR=%RUNANT_DIR%..\..\..
if not exist "%STUDIO_DIR%"\eclipse\jre  echo ERROR: incorrect STUDIO_DIR=%STUDIO_DIR%
if not exist "%STUDIO_DIR%"\eclipse\jre  goto done

:java
if not $%JAVA_DIR%$==$$ goto workspace
set JAVA_DIR=%STUDIO_DIR%\eclipse\jre\bin

:workspace
if not $%WORKSPACE%$==$$ goto check
REM #######################################################
REM ##### you must edit the "WORKSPACE" setting below #####
REM #######################################################
REM *********** The location of your workspace ************
set WORKSPACE=X:\MyWorkspace

:check
REM ************* The location of your workspace *****************
if not exist "%WORKSPACE%" echo ERROR: incorrect workspace=%WORKSPACE%, 
	edit this runAnt.bat and correct the WORKSPACE envar
if not exist "%WORKSPACE%" goto done

set LOCATIONS=-DSTUDIO.DIR=%STUDIO_DIR% 
	-DSTUDIO.RUNANT=%RUNANT_DIR% 
	-DSTUDIO.WORKSPACE=%WORKSPACE%

:run
@echo on
"%JAVA_DIR%\java"   -cp "%STUDIO_DIR%\eclipse\startup.jar" 
	org.eclipse.core.launcher.Main
     -application com.ibm.etools.j2ee.ant.RunAnt  
     -data "%WORKSPACE%"  %*
@if %ERRORLEVEL% EQU 0 goto done
@if %ERRORLEVEL% EQU 13 echo runAnt BUILD FAILED.
@if %ERRORLEVEL% EQU 13 goto pause
@if %ERRORLEVEL% EQU 15 echo WORKSPACE is already BEING USED (Studio-v5 has already locked it).
@if %ERRORLEVEL% EQU 15 goto pause
@if %ERRORLEVEL% EQU 23 echo totally clean (UNINITIALIZED) workspace, it is now setup. will rerun...
@if %ERRORLEVEL% EQU 23 goto run
@echo runAnt FAILED? (return code %ERRORLEVEL%)
:pause
@pause

:done

This example uses a workspace named D:\HeadlessAnt, and for simplicity, a simple project AntFiles, which contains runAnt.bat and build.xml. Here is the customization of runAnt.bat according to the Application Developer installation location on my computer:

Customized runAnt.bat
echo off

setlocal
REM The root directory of your Studio installation
set WSAD=C:\WSAD512

REM *********** The location of your workspace ************
set WORKSPACE=d:\HeadlessAnt

REM ************* The location of your workspace *****************
if not exist "%WORKSPACE%" echo ERROR: incorrect workspace=%WORKSPACE%, 
	edit this runAnt.bat and correct the WORKSPACE envar
if not exist "%WORKSPACE%" goto done

:run
echo on
%WSAD%\eclipse\jre\bin
	-cp %WSAD%\eclipse\startup.jar org.eclipse.core.launcher.Main
     -application com.ibm.etools.j2ee.ant.RunAnt 
     -data %WORKSPACE%  %*

@if %ERRORLEVEL% EQU 0 goto done
@if %ERRORLEVEL% EQU 13 echo runAnt BUILD FAILED.
@if %ERRORLEVEL% EQU 13 goto pause
@if %ERRORLEVEL% EQU 15 echo WORKSPACE is already BEING USED (Studio-v5 has already locked it).
@if %ERRORLEVEL% EQU 15 goto pause
@if %ERRORLEVEL% EQU 23 echo totally clean (UNINITIALIZED) workspace, it is now setup.  will rerun...
@if %ERRORLEVEL% EQU 23 goto run
@echo runAnt FAILED? (return code %ERRORLEVEL%)
:pause
@pause

:done

Creating the initial build.xml

A typical build.xml file that builds the project using the buildProject Ant task:

build.xml
<?xml version="1.0" encoding="UTF-8"?>

<project name="Hello" default="build">
<target name="build">

<projectBuild ProjectName="Hello" failonerror="false" DebugCompilation="false" BuildType="full" />

<getProjectData Basedir="D:\HeadlessAnt\HelloProject" />
<echo message="getProjectData: projectName=${projectName} nature=${natureName}" />

</target>
</project>

Invocation of the build

A typical Ant command invocation: runAnt -buildfile d:\HeadlessAnt\MyAntBuild.xml

Since build.xml is in the same folder as runAnt.bat, you don't need to use the -buildfile flag. Also, since the default build file name build.xml is used, the actual invocation is simpler: D:\HeadlessAnt\AntFiles>runAnt

Some build- and run-time problems are caused by mismatches in versions of Ant or the Java™ Run Time. WebSphere Studio Application Developer V5.1.2 ships with Ant 1.5.3 and JDK 1.3.1. Rational Application Developer V6 ships with Ant 1.6.2 and JDK 1.4.2.

To ensure that the headless build uses the same compiler as the GUI would, add the following property to the Ant script:

setting Ant property to use the Eclipse JDT compiler:
<target name="properties" if "eclipse.running">
<property name="build.compiler" org.eclipse.jdt.core.JDTCompilerAdapter/>
</target>

Check the eclipse.running property to ensure that the Eclipse JDT compiler is used only if running in Application Developer or some other Eclipse-based application.

For debugging, it's helpful at the beginning of each Ant run to print the versions of Ant and the Java Run-time Environment (JRE) that you are using. To do so, use some of the Ant built-in properties and modify build.xml:

modified build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="Hello" default="build">
<target name="build">
<echo>${ant.version}</echo>
<echo>Java ${ant.java.version}</echo>
...

Available Ant tasks

To see a complete list of the Ant tasks, click Window => Preferences and select Ant as shown below in Figure 1 (for WebSphere Studio Application Developer V5.1.2 ) or Figure 2 (for Rational Application Developer V6). For more details on various Ant tasks, access the Application Developer online help and search on "headless."

Figure 1. Ant tasks available in Application Developer 5.1.2
Ant tasks available in Application Developer 5.1.2
Figure 2. More Ant tasks were made available in RAD 6.0
Ant tasks available in RAD 6.0

Another approach is to search the Application Developer installation directory for all plugin.xml files containing the characters antTask. This information is also useful when adding your own custom Ant Tasks.

Example of Ant tasks defined in various plugin's plugin.xml
      <antTask
            library="runtime/antextras.jar"
            name="projectBuild"
            class="com.ibm.etools.ant.extras.ProjectBuild">
      </antTask>
      <antTask
            library="runtime/antextras.jar"
            name="getJavacErrorCount"
            class="com.ibm.etools.ant.extras.GetJavacErrorCount">
      </antTask>
      <antTask
            library="runtime/antj2ee.jar"
            name="earExport"
            class="com.ibm.etools.j2ee.ant.EARExport">
      </antTask>
      ...
      <antTask
         name="eclipse.incrementalBuild"
         class="org.eclipse.core.resources.ant.IncrementalBuild"
         library="ant_tasks/resources-ant.jar">
      </antTask>
      <antTask
         name="eclipse.refreshLocal"
         class="org.eclipse.core.resources.ant.RefreshLocalTask"
         library="ant_tasks/resources-ant.jar">
      </antTask>
      ...

Best practices

Before tackling headless builds, ensure that normal Application Developer builds are successful, and that the Ant build works correctly when invoked from the Application Developer menu. Launching Ant within Application Developer is easy, since Eclipse recognizes build.xml, and when you right-click on it, its context menu has a Run Ant selection. Correct any build problems that appear in the Application Developer console view. The Ant flag -debug helps in troubleshooting Ant-specific problems. As mentioned above, ensure consistency between the Ant and the JRE versions used when running under Application Developer versus running headless. For Ant-specific problems, your best information source is the Apache Ant Web site.

To further ensure that your environment is correct before tackling headless Ant builds, check that the migration from Websphere Studio Application Developer V5.1.2 to Rational Application Developer V6 has been done at the workspace level and not at the project level.

Another possible problem when using headless Ant in Application Developer is using the Ant script to check out code directly from the source control repository and then running the projectBuild Ant task. If the check out is done by directly issuing commands specific to the repository instead of using an Ant task provided by the SCM plug-in, then the workspace metadata is not synchronized and is not aware of the latest checkout. Therefore an incremental build will run based on the last known state before the checkout. If the SCM plug-in does not have an Ant task for checking out, the alternative is to do the checkout as before, then run the eclipse.refreshLocal Ant task provided by Eclipse, which updates the metadata to synchronize it with the state of the file system.

The eclipse.refreshLocal Ant task enables the headless Ant execution to fulfill the same requirement as GUI users are asked to fulfill, as described in the Rational Application Developer V6 online help: "Don't forget to refresh! Whenever you use external tools to modify workspace files, you must perform a refresh from within Eclipse to make the workspace aware of the changes. If you get a "Resource out of sync" error in Eclipse, it means that resources in Eclipse have been modified outside of Eclipse. One solution is to perform a refresh (available from a resource's popup menu) on any resources or projects that were modified outside of Eclipse. There is also a Workbench preference to refresh automatically."

A less frequent but more serious possible problem when using the headless Ant feature in Application Developer is caused by incorporating Application Developer plug-ins that do not support headless Ant. Some plug-ins access GUI components, which obviously will not work in headless mode because no GUI is available. This problem usually breaks the headless Ant build, and generates a stack trace in the .log file similar to the one below, which was caused by attempting to invoke an editor, which obviously is not available in headless mode:

exception stack trace from .log file
  java.lang.NullPointerException
	at org.eclipse.ui.internal.registry.EditorRegistry.initializeFromStorage
		(EditorRegistry.java:460)
	at org.eclipse.ui.internal.registry.EditorRegistry.<init>(EditorRegistry.java:64)
	at org.eclipse.ui.internal.WorkbenchPlugin.getEditorRegistry(WorkbenchPlugin.java:234)
	at com.ibm.etools.struts.StrutsResourceChangeListener.unsetRegistration
		(StrutsResourceChangeListener.java:364)
	at com.ibm.etools.struts.StrutsResourceChangeListener.checkForStrutsConfigFile
		(StrutsResourceChangeListener.java:233)
	at com.ibm.etools.struts.StrutsResourceChangeListener.checkForStrutsConfigFile
		(StrutsResourceChangeListener.java:211)
	at com.ibm.etools.struts.StrutsResourceChangeListener.visit
		(StrutsResourceChangeListener.java:178)
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java(Compiled Code))
	at org.eclipse.core.internal.events.ResourceDelta.accept(ResourceDelta.java:52)
	at com.ibm.etools.struts.StrutsResourceChangeListener.resourceChanged
		(StrutsResourceChangeListener.java:141)
	at org.eclipse.core.internal.events.NotificationManager$1.run(NotificationManager.java:137)
	at org.eclipse.core.internal.runtime.InternalPlatform.run
		(InternalPlatform.java(Inlined Compiled Code))
	at org.eclipse.core.runtime.Platform.run(Platform.java(Compiled Code))
	at org.eclipse.core.internal.events.NotificationManager.notify(NotificationManager.java:152)
	at org.eclipse.core.internal.events.NotificationManager.broadcastChanges
	(NotificationManager.java:67)
	at org.eclipse.core.internal.resources.Workspace.broadcastChanges(Workspace.java:161)
	at org.eclipse.core.internal.resources.Workspace.endOperation(Workspace.java(Compiled Code))
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1600)
	at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:85)
	at com.ibm.etools.ant.extras.ProjectBuild.execute(ProjectBuild.java:64)
	at org.apache.tools.ant.Task.perform(Task.java:341)
	at org.apache.tools.ant.Target.execute(Target.java:309)
	at org.apache.tools.ant.Target.performTasks(Target.java:336)
	at org.apache.tools.ant.Project.executeTarget(Project.java:1339)
	at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:397)
	at org.apache.tools.ant.taskdefs.CallTarget.execute(CallTarget.java:143)
	at org.apache.tools.ant.Task.perform(Task.java:341)
	at org.apache.tools.ant.Target.execute(Target.java:309)
	at org.apache.tools.ant.Target.performTasks(Target.java:336)
	at org.apache.tools.ant.Project.executeTarget(Project.java:1339)
	at org.apache.tools.ant.Project.executeTargets(Project.java:1255)
	at org.eclipse.ant.internal.core.ant.InternalAntRunner.run(InternalAntRunner.java:569)
	at org.eclipse.ant.internal.core.ant.InternalAntRunner.run(InternalAntRunner.java:493)
	at java.lang.reflect.Method.invoke(Native Method)
	at org.eclipse.ant.core.AntRunner.run(AntRunner.java:464)
	at com.ibm.ant.extras.RunAnt.run(RunAnt.java:27)
	at org.eclipse.core.internal.boot.InternalBootLoader.run(InternalBootLoader.java:858)
	at org.eclipse.core.boot.BootLoader.run(BootLoader.java:461)
	at java.lang.reflect.Method.invoke(Native Method)
	at org.eclipse.core.launcher.Main.basicRun(Main.java:291)
	at org.eclipse.core.launcher.Main.run(Main.java:747)
	at org.eclipse.core.launcher.Main.main(Main.java:583)

Another problem, infrequent but puzzling, occurs when running a headless build after an upgrade of the Application Developer that needs a restart. When running Application Developer from the GUI, the executable wsappdev.exe detects the request for the restart (signal 23) and initiates the restart. But when running headless, the first run will usually fail (since signal 23 is unexpected), but the second headless run will succeed. You have three alternatives:

  • Run Application Developer from the GUI after first applying an upgrade.
  • Handle the signal 23 in the Ant script.
  • Simply be aware of this behavior and run the headless Ant twice.

Acknowledgements

The author would like to thank Barry Searle, of the IBM Toronto Lab, for his review and helpful comments.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Java technology, Rational, DevOps
ArticleID=83755
ArticleTitle=Troubleshooting headless Ant builds with Rational Application Developer
publish-date=04272005