Friday, February 15, 2008

KB: NetBeans and CruiseControl

Guide for building NetBeans projects using CruiseControl.

Contents

Overview

NetBeans allows users to create libraries and add references to them in projects. The IDE automatically adds references to application server dependencies for EJB and web projects as well. This works until one tries to build an application outside the IDE. The libraries are external to the project and are lost when the project is moved to another location. The IDE also saves a number of user specific paths in nbproject/private/private.properties.

A dependency management system such as Maven is one solution however, for a small project this can be overkill. Another solution includes adding library jars directly to the project in a /lib folder. Many projects do this and it works quite well. Using this approach with NetBeans makes it difficult to tell which jars belonged to which libraries. The solution described here allows a small team to manage a single copy of all third party libraries across all projects under CruiseControl.

The guide does not cover the installation and configuration of CruiseControl. If you need to install and configure CruiseControl, refer to this guide.

Library Repository

The first step is to create a library repository that will be used by the build system. This repository should also be used by individual developers as the authoritative source of libraries for their projects. While not automated, this system still allows users to create and manage libraries using the IDE with caveat the user is responsible for keeping the build system properties file updated with any new libraries that were obtained from the repository. On the machine running CruiseControl, create a structure to hold the library jars.

Example:
cruisecontrol_deps
|-- glassfish-v2
|   |-- activation.jar
|   |-- appserv-jstl.jar
|   |-- appserv-tags.jar
|   |-- appserv-ws.jar
|   |-- javaee.jar
|   |-- jsf-impl.jar
|   |-- mail.jar
|   |-- webservices-rt.jar
|   `-- webservices-tools.jar
|-- javadb
|   |-- derby.jar
|   |-- derbyclient.jar
|   `-- derbynet.jar
|-- jaxws21
|   |-- FastInfoset.jar
|   |-- activation.jar
|   |-- api
|   |   |-- jaxb-api.jar
|   |   |-- jaxws-api.jar
|   |   |-- jsr173_api.jar
|   |   |-- jsr181-api.jar
|   |   |-- jsr250-api.jar
|   |   `-- saaj-api.jar
|   |-- http.jar
|   |-- jaxb-impl.jar
|   |-- jaxb-xjc.jar
|   |-- jaxws-rt.jar
|   |-- jaxws-tools.jar
|   |-- resolver.jar
|   |-- saaj-impl.jar
|   |-- sjsxp.jar
|   |-- stax-ex.jar
|   `-- streambuffer.jar
|-- junit
|   |-- junit-3.8.2.jar
|   `-- junit-4.1.jar
|-- log4j
|   `-- log4j-1.2.15.jar
|-- rest
|   |-- asm-3.1.jar
|   |-- comresrcgen.jar
|   |-- grizzly-http-webserver-1.7.0.jar
|   |-- http.jar
|   |-- jdom-1.0.jar
|   |-- jersey.jar
|   |-- jettison-1.0-RC1.jar
|   |-- jsp-api-2.0-20040521.jar
|   |-- jsr311-api.jar
|   |-- persistence-api-1.0.jar
|   |-- rome-0.9.jar
|   `-- wadl2java.jar
`-- toplink
    |-- toplink-essentials-agent.jar
    `-- toplink-essentials.jar

Build System Properties File

The nbproject/private/private.properties file contains a number of definitions including classpath information needed to compile and run a project. Create a second version of this file, cc.properties in the nbproject folder. This file will be used by CruiseControl to resolve the project's library dependencies instead of the private.properties file. Edit the paths to reflect the location of the repository created in the previous step.

Example:
j2ee.platform.is.jsr109=true

javac.debug=false

jaxws.endorsed.dir=/opt/cruisecontrol_deps/jaxws21/api

libs.Log4J.classpath.libfile.1=/opt/cruisecontrol_deps/log4j/log4j-1.2.15.jar

libs.JAVADB_DRIVER_LABEL.classpath.libfile.1=/opt/cruisecontrol_deps/javadb/derby.jar
libs.JAVADB_DRIVER_LABEL.classpath.libfile.2=/opt/cruisecontrol_deps/javadb/derbyclient.jar
libs.JAVADB_DRIVER_LABEL.classpath.libfile.3=/opt/cruisecontrol_deps/javadb/derbynet.jar

libs.restlib.classpath.libfile.1=/opt/cruisecontrol_deps/rest/jsr311-api.jar
libs.restlib.classpath.libfile.10=/opt/cruisecontrol_deps/jaxws21/api/jaxb-api.jar
libs.restlib.classpath.libfile.11=/opt/cruisecontrol_deps/jaxws21/jaxb-impl.jar
libs.restlib.classpath.libfile.12=/opt/cruisecontrol_deps/jaxws21/jaxb-xjc.jar
libs.restlib.classpath.libfile.13=/opt/cruisecontrol_deps/jaxws21/api/jsr173_api.jar
libs.restlib.classpath.libfile.14=/opt/cruisecontrol_deps/rest/rome-0.9.jar
libs.restlib.classpath.libfile.15=/opt/cruisecontrol_deps/rest/jdom-1.0.jar
libs.restlib.classpath.libfile.16=/opt/cruisecontrol_deps/rest/jettison-1.0-RC1.jar
libs.restlib.classpath.libfile.17=/opt/cruisecontrol_deps/rest/asm-3.1.jar
libs.restlib.classpath.libfile.18=/opt/cruisecontrol_deps/rest/grizzly-http-webserver-1.7.0.jar
libs.restlib.classpath.libfile.2=/opt/cruisecontrol_deps/rest/jersey.jar
libs.restlib.classpath.libfile.3=/opt/cruisecontrol_deps/rest/jsp-api-2.0-20040521.jar
libs.restlib.classpath.libfile.4=/opt/cruisecontrol_deps/rest/persistence-api-1.0.jar
libs.restlib.classpath.libfile.5=/opt/cruisecontrol_deps/jaxws21/activation.jar
libs.restlib.classpath.libfile.6=/opt/cruisecontrol_deps/jaxws21/api/jsr250-api.jar
libs.restlib.classpath.libfile.7=/opt/cruisecontrol_deps/rest/http.jar
libs.restlib.classpath.libfile.8=/opt/cruisecontrol_deps/rest/wadl2java.jar
libs.restlib.classpath.libfile.9=/opt/cruisecontrol_deps/jaxws21/api/jaxws-api.jar

libs.Log4J.classpath=/opt/cruisecontrol_deps/log4j/log4j-1.2.15.jar
libs.JAVADB_DRIVER_LABEL.classpath=/opt/cruisecontrol_deps/javadb/derby.jar:/opt/cruisecontrol_deps/javadb/derbyclient.jar:/opt/cruisecontrol_deps/javadb/derbynet.jar
libs.restapi.classpath=/opt/cruisecontrol_deps/rest/jsr311-api.jar
libs.restlib.classpath=/opt/cruisecontrol_deps/rest/jsr311-api.jar:/opt/cruisecontrol_deps/jaxws21/api/jaxb-api.jar:/opt/cruisecontrol_deps/jaxws21/jaxb-impl.jar:/opt/cruisecontrol_deps/jaxws21/jaxb-xjc.jar:/opt/cruisecontrol_deps/jaxws21/api/jsr173_api.jar:/opt/cruisecontrol_deps/rest/rome-0.9.jar:/opt/cruisecontrol_deps/rest/jdom-1.0.jar:/opt/cruisecontrol_deps/rest/jettison-1.0-RC1.jar:/opt/cruisecontrol_deps/rest/asm-3.1.jar:/opt/cruisecontrol_deps/rest/grizzly-http-webserver-1.7.0.jar:/opt/cruisecontrol_deps/rest/jersey.jar:/opt/cruisecontrol_deps/rest/jsp-api-2.0-20040521.jar:/opt/cruisecontrol_deps/rest/persistence-api-1.0.jar:/opt/cruisecontrol_deps/jaxws21/activation.jar:/opt/cruisecontrol_deps/jaxws21/api/jsr250-api.jar:/opt/cruisecontrol_deps/rest/http.jar:/opt/cruisecontrol_deps/rest/wadl2java.jar:/opt/cruisecontrol_deps/jaxws21/api/jaxws-api.jar

j2ee.platform.classpath=/opt/cruisecontrol_deps/glassfish-v2/javaee.jar:/opt/cruisecontrol_deps/glassfish-v2/jsf-impl.jar:/opt/cruisecontrol_deps/glassfish-v2/activation.jar:/opt/cruisecontrol_deps/glassfish-v2/appserv-tags.jar:/opt/cruisecontrol_deps/glassfish-v2/mail.jar:/opt/cruisecontrol_deps/glassfish-v2/appserv-jstl.jar:/opt/cruisecontrol_deps/glassfish-v2/webservices-tools.jar:/opt/cruisecontrol_deps/glassfish-v2/webservices-rt.jar:/opt/cruisecontrol_deps/glassfish-v2/appserv-ws.jar
j2ee.platform.wscompile.classpath=/opt/cruisecontrol_deps/glassfish-v2/j2ee.jar:/opt/cruisecontrol_deps/glassfish-v2/saaj-api.jar:/opt/cruisecontrol_deps/glassfish-v2/saaj-impl.jar:/opt/cruisecontrol_deps/glassfish-v2/jaxrpc-api.jar:/opt/cruisecontrol_deps/glassfish-v2/jaxrpc-impl.jar:/opt/cruisecontrol_deps/glassfish-v2/endorsed/jaxp-api.jar:/opt/cruisecontrol_deps/glassfish-v2/appserv-ws.jar:/opt/cruisecontrol_deps/glassfish-v2/webservices-tools.jar:/opt/cruisecontrol_deps/glassfish-v2/webservices-rt.jar
j2ee.platform.wsgen.classpath=/opt/cruisecontrol_deps/glassfish-v2/webservices-tools.jar:/opt/cruisecontrol_deps/glassfish-v2/webservices-rt.jar:/opt/cruisecontrol_deps/glassfish-v2/tools.jar:/opt/cruisecontrol_deps/glassfish-v2/appserv-jstl.jar:/opt/cruisecontrol_deps/glassfish-v2/javaee.jar:/opt/cruisecontrol_deps/glassfish-v2/appserv-ws.jar:/opt/cruisecontrol_deps/glassfish-v2/mail.jar:/opt/cruisecontrol_deps/glassfish-v2/activation.jar
j2ee.platform.wsimport.classpath=/opt/cruisecontrol_deps/glassfish-v2/webservices-tools.jar:/opt/cruisecontrol_deps/glassfish-v2/webservices-rt.jar:/opt/cruisecontrol_deps/glassfish-v2/tools.jar:/opt/cruisecontrol_deps/glassfish-v2/appserv-jstl.jar:/opt/cruisecontrol_deps/glassfish-v2/javaee.jar:/opt/cruisecontrol_deps/glassfish-v2/appserv-ws.jar:/opt/cruisecontrol_deps/glassfish-v2/mail.jar:/opt/cruisecontrol_deps/glassfish-v2/activation.jar
j2ee.platform.wsit.classpath=

libs.junit.classpath=/opt/cruisecontrol_deps/junit/junit-3.8.2.jar
libs.junit_4.classpath=/opt/cruisecontrol_deps/junit/junit-4.1.jar

Project Build File

When a project is imported to SVN for example, NetBeans ignores the private folder under nbproject. To get CruiseControl to use the cc.properties file created above, we can use the fact that the private folder will be missing when the project is checked out by the build system. Modify the build.xml in the project root folder as follows:
<target name="-pre-init">
   <available file="nbproject/private" property="privatedir.exists" type="dir"></available>
</target>

<target depends="-pre-init" name="-init-cc" unless="privatedir.exists">
    <property file="nbproject/cc.properties"></property>
</target>

<target depends="-pre-init, -init-cc" if="privatedir.exists" name="-init-private">
    <property file="nbproject/private/private.properties"></property>
</target>
Committing the modified project to the SCM should trigger CruiseControl and result in a successful build.

Managing the Process

  • The repository is the official source of libraries used by developers in their projects.
  • A single developer should be selected to manage the repository.
  • Give all developers read access to the repository (SMB, NFS, SSH, etc.).
  • Remember to update the build system properties file with any new dependencies before check in.
To Top