Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Agility meets the Waterfall

Agile best practices in Waterfall-based Java enterprise development

  • Print
  • Feedback

Page 3 of 4

Automated builds

The first requirement says that you should be able to start up a virgin machine, do a checkout, and fully build the system without a hitch. Automated builds, a staple of agile development, would resolve this requirement. Many developers use IDEs that include include some kind of build management process. These are helpful for faster development, but you also need a script to build the project independently. Ant and Maven are two tools commonly used for build automation in Java-based projects. Gant also is gaining ground with developers who favor Groovy. In any case, build scripts are not proprietary and can be executed on any platform.

A successful build automation process for the example Java EE project would need to achieve the following:

  1. The application code available in the SVN repository should contain the code with all default configuration steps implemented that otherwise would have to be performed by the developer. It should also contain a build script that updates the configuration properties file for each working environment (local, development, test, production, etc.) instead of updating them manually.
  2. A master build script should be created that contains the target of all application components. This script should make it possible to build the entire project with a single click.
Code quality measurement
Build automation isn't limited to just compiling, building, and deploying the application. Many other important tasks can be included as part of an automated build. For instance, you can execute xUnit test cases, or get the HTML output of static code-checker tools like CheckStyle or PMD, which could be sent to various project stakeholders. You can also integrate code coverage tools such as EMMA or Cobertura with your automated test cases.

It is a good idea to test the efficacy of your automated build setup. For this a fresh developer should review all of the above-mentioned implementation steps to validate the ability to set up, build, and deploy the entire application with minimal effort. This is an iterative process; if the developer gets stuck somewhere, the process should be revised and updated.

Every Java project should also contain a readme.txt in the root project directory that describes manual steps (steps that cannot be performed by a build script) to be performed by the developer. For instance, certain projects may need to make changes in the JRE security settings for encryption implementations, or for JAAS configurations. The readme file should also list the necessary steps to build and deploy the application on the server.

Build setup: The master build script

Given that this project consists of numerous EAR and WAR files, it’s a pain to build the entire application by executing the individual Ant build scripts for each application component. Manual builds require the person responsible (in this case the build manager) to remember in what order he or she has to execute all the build targets. The solution to this kind of problem, as mentioned above, is to have a master build script for the project.

Note that it is still good to have individual build targets in the root directory of each component (or module) of the Java project. The master build script simply orchestrates all the individual build targets. Listing 1 is an example of a master build script.

Listing 1. A master build script using Ant

<target name="build-ABCSecurityServices"

                depends="call-ABCSecurityServices-build,export-abc-securityservices.jar ">

                <copy todir="${artifact}/${env}">

                        <fileset dir="${SecurityServices}/dist">

                                <include name="*.ear"/>

                        </fileset>

                </copy>

        </target>

        <target name="call-ABCSecurityServices-build">

                <ant antfile="${Security}/ABCSecurityServices/build.xml" inheritAll="false" target="all" />

        </target>

        <target name="export-abc-securityservices.jar">
                <copy file="${abc-securityservices.jar}" toFile="${project.internallib.dir}/abc-securityservices.jar"/>
        </target>

The Ant master build script in Listing 1 calls call-ABCSecurityServices-build available in build.xml of the ABCSecurityServices Java project. So, instead of containing individual build targets, the master build script just delegates the task and orchestrates multiple tasks. It also decides the order of tasks to be executed. All artifacts such as EAR and WAR files are copied to a single location, from which they can be easily deployed.

Given that the build manager needs to make build for multiple environments, it also would be a good idea to externalize the factors that change from environment to environment. Most of the time, these are application configuration files. Instead of including them inside EAR/WAR files, they can be externalized and placed on the application server classpath. In this way, EAR/WAR files will not change from environment to environment. The build script will just change these configuration properties based on the environment. Naturally, this task also should be automated.

The master build script makes the build manager's life a lot easier by realizing the goal of making the build with a single click.

Why not Maven?
It could be argued that Maven is a better build tool than Ant for a development scenario involving multiple Java projects. Agreed. Practically speaking, however, a good percentage of Java EE projects still use Ant for various reasons, including ease-of-use, legacy code, and Maven's dependence on an online repository. I chose to focus on Ant because it is a likely solution for many Java enterprise shops.

Test automation

In many Waterfall-based projects the developer writes a software component and then performs a set of unit tests manually. In the future, if the developer needs to modify the same component, she or he must perform the entire manual unit testing process again. Often, when the changes are small, developers just test the impacted functionality. This seems reasonable given time constraints or the assumption that the change will not affect other parts of application. Unfortunately, even small changes can break related functionality, which won't be discovered until the entire application is tested.

JUnit is an answer to such problems. In JUnit a separate file contains all the test cases for a given component, so they can be run at the click of a button. JUnit makes it easy to test software components in isolation and also easily run numerous tests. JUnit is also a valuable component in test-driven development, where developers actually write test cases to test the impact of a desired change throughout the system before doing any coding.

Some developers argue against test automation, saying "Why should I waste time writing test cases when I can make the change and test the functionality manually in 20 minutes?" While this is a convincing argument on the surface, it falls apart when you think about today's accelerated development cycle, where the same manual process might need to happen 10 times in a row. Manual testing also doesn't leave much documentation for new developers; and then there is the human tendency to err.

Many ways to test

There are many ways to expand on the basic approach of test automation, and at least a handful of very good tools for specific types of scenarios. DBUnit, for instance, is a unit testing framework built on top of JUnit that is used to put your database into a known state between test runs. DBUnit is helpful in cases where the side-effects of component execution are changes in the database, or where you need to ensure a certain state in the database before you can execute test cases for a given component. Combining DBUnit and JUnit also is useful for testing components that have extensive database-driven operations.

EasyMock is an open source utility that can be used to generate mock objects or mock interfaces so that you don't have to wait around for third-party code. Using EasyMock also means you don't waste time writing mock objects when you could be testing your code.

DBUnit and EasyMock are two tools that provide solutions for individual component testing. But how about the problem mentioned by the developer in the original scenario, whose module is the tenth step in the overall application design? How can that developer ensure that his module is going to work with all the other modules?

The key to this problem is creating end-to-end test cases for various modules, so that modules are combined and tested as a group. Integration testing can be done using any of the above-mentioned tools or frameworks combined. In some cases you may require a technical infrastructure for integration testing. One option in this case is to use the Spring testing module without using the Spring framework as a whole.

Selenium is another excellent and easy-to-learn testing tool that is used to test Web applications. Selenium tests run directly in a browser and mimic the user's interaction with the system and UI.

Another open source tool that can round out your test automation suite is Cobertura. Rather than just count the number of test cases at the end of your development cycle, Cobertura lets you measure code coverage, or how much of your code, line by line, has actually been tested. Cobertura reports on the percentage of code tested and not tested for each file in your application.

Now we get to the best part of all the above tools and frameworks: using them in a continuous integration environment.

  • Print
  • Feedback

Resources
  • "J2EE project execution: Some best practices" (ShriKant Vashishtha, JavaWorld, November 2005) explains how template code, a developer's handbook, and automated code reviews can improve Java enterprise project execution.
  • "Introducing continuous integration" (Paul Duvall, Steve Matyas, Andrew Glover; JavaWorld, June 2007) is an overview of CI process and tools, excerpted from Continuous Integration: Improving Software Quality and Reducing Risk.
  • Java Power Tools (John Ferguson Smart, O'Reilly, April 2008) is a guide to open source tools for the entire software development lifecycle, including many that were mentioned in this article. JavaWorld recently interviewed the author about some of his favorite tools for test automation and CI.
  • "Groovy-power automated builds with Gant" (Klaus P. Berg, JavaWorld, February 2008) introduces the newest automated-build tool on the block: Groovy+Ant.
  • "Best practices for test-driven development" (Michael Grove and Brooks Bollich, JavaWorld, May 2004) introduces TDD -- an agile technique not so suitable for Waterfall-based projects -- and offers background on the use of mock objects in test automation.
  • "The demise of the Waterfall model Is imminent and other urban myths" (Phillip A. Laplante and Colin J. Neill, ACM Queue, February 2004) seeks the truth behind some popular folklore of computer programming.
  • Forrester Research has been tracking agile adoption for several years, with the most recent survey results released in February 2008.
  • "Agile people still don't get it" (Cedric Beust, Otaku, June 2006) expresses the occasional disconnect between agile evangelism and the challenge of organizing "huge code bases growing thousands of lines of code every day under the combined push of hundreds of a developers, all with their personal background, education and bias."
  • "Software testing with Spring framework" (Srini & Kavitha Penchikala, InfoQ, November 2007) is an overview of specifically agile software testing techniques like TDD, and of integration testing with the Spring framework.
  • "Testing persistent objects without Spring" (James Richardson, Time4Tea.com, November 2007) shows one way to test persistent classes without Spring.
  • Martin Fowler is always a good read. Here he explains the process of continuous integration.
  • " Philosophy of test automation" is an excerpt from xUnit Test Patterns (Gerard Meszaros, Addison-Wesley, May 2007).
  • See the JavaWorld Development Tools Research Center for hands-on introductions to the tools discussed in this article.
  • Also see Network World's IT Buyer's Guides: Side-by-side comparison of hundreds of products in over 70 categories.

Tools discussed in this article