Michael Gendelman

Subscribe to Michael Gendelman: eMailAlertsEmail Alerts
Get Michael Gendelman: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Related Topics: Apache Web Server Journal

Apache Web Server: Article

Building and Deploying Applications with Ant

Building and Deploying Applications with Ant

As a software developer I enjoy designing and developing new systems, but I don't enjoy spending time on configuration. Building and deploying WebLogic applications can quickly become complex.

Each deployed unit, whether it's an EJB JAR File, WAR File, or EAR File requires deployment descriptors to be placed in specific directories. The correct classes must be included, and in the correct directories. Changes to a common class may require the redeployment of the entire application. Mistakes in the build process can require hours wasted debugging.

Use of a proprietary IDE, while able to automate the build process for a single developer, can become a nightmare when trying to deploy someone else's work. There are several Java IDEs on the market today that provide automation for building and deploying WLS applications. These tools usually store the build and deployment information in a proprietary format.

While it is possible to save this information and transfer it to other developers, it can present several problems. First, all of the developers need to work with the same tool. Second, some tools save all of the deployment information into a single file, making it difficult to synchronize to a single copy. Third, the tools don't usually allow for a high degree of flexibility, making it difficult to deploy to different servers, deploy multiple components, choose between multiple deployment options, and deploy the components without using the IDE.

Build Tools
Ant is a build tool made specifically for Java. Build or make tools have been around for years, and they are used to automate the build process of applications. They usually run compilers, provide access to the file system, and handle a variety of other tasks associated with building an application. These tools are usually tied very closely to the operating system. They generally use a proprietary file format that is often hard to edit and easy to make mistakes with. While most make/build tools are capable of building Java applications, they do not provide operating system independence, nor do they closely integrate with Java.

Why Ant?
Ant was created as part of Apache's Jakarta Project. It has integrated Java tasks such as java, javac, JAR, WAR, and many others. It also supports many file system tasks, making them operating-system independent. The scripts you write on Windows will work equally well on Solaris. If Ant doesn't contain what you need, it can be extended using Java. And because Ant is extendable, it's being integrated with almost everything, including WLS.

I will demonstrate how to integrate Ant to automate the build and deployment process of WLS applications. There are many different ways to do this, and no one way is the best. Creating Ant scripts is an iterative process, requiring refactoring, just like good code. I will focus on using Ant to build and deploy WLS applications. General information about Ant can be found at http://jakarta.apache.org/ant.

Ant doesn't replace the Java IDEs. Developers should still use whatever tools they are comfortable with to develop code and write deployment descriptors, but when a component is ready for integration into the project build, an Ant build.xml script should be included. The build.xml file is an XML file that describes the build and deployment process of your application or component.

With Ant, you still have to do all of the configuring, but then Ant automates the process. Ant allows you to define your packaging, build, and deployment processes in XML. The XML becomes a living documentation; everyone on the team can read, modify, and most importantly, execute the XML Ant scripts. The process can also be refined by updating the XML build scripts. Ant makes it possible to quickly perform complex and tedious operations without mistakes.

How to Get Started With Ant
Before we can start, we need to set up the environment. With WLS, this couldn't be easier. As of WLS 6.1, Ant is included in weblogic.jar. WLS now includes Ant build scripts with its example code. BEA includes an Ant bat and shell script in the WLS bin directory. In other words, by installing WLS 6.1, you've already installed Ant. If you're using an older version of WebLogic Server, you'll need to download Ant from http://jakarta.apache.org/ant/manual/install.html. Simply download the latest version, and unpack it. It will contain the Ant batch and script files in its bin directory.

Lets start by describing our example application. The application will contain two EJBs: EJBOne and EJBTwo. EJBOne and its helper classes are located in package mypackage.ejbone, EJBTwo and its helper classes are located in package mypackage. ejbtwo. The application will also contain servlets and JSPs. The servlet and JSP helper classes will reside in the package mypackage.client and the JSPs will reside in a directory called content, along with HTML and image resources. Here I detail the layout of the sample application directory structure:

 

project/src/content
project/scr/mypackage/client
project/scr/mypackage/common
project/src/mypackage/ejbone
project/src/mypackage/ejbone/notneeded
project/src/mypackage/ejbone/META-INF
project/src/mypackage/ejbtwo
project/src/mypackage/ejbtwo/META-INF
project/src/ear/META-INF
project/staging
project/build

Using Ant With WLS
Project Properties

The first thing I do, although it's not required, is define a property file. The property file contains information that may change between different development environments within a given project. The following is an example of a property file. The file could be named anything, but for this example we will call it config.properties.

 

WL_HOME=c:/bea/wlserver6.1
STAGING=c:/project/staging
BUILD=c:/project/build
SOURCE=c:/project/src
DEVELOPMENTSERVER= http://localhost:7001
TESTERVER=http://testserver:80

The first property in the file is WL_HOME. WL_HOME is important for several reasons. First, each development environment may have WLS installed in different locations. Second, as you migrate to newer versions of WLS, you can control which version of WLS is used during the build process. The next property is STAGING. It contains the location used to store all of the components (e.g., JAR, EAR, WAR) before they are deployed. BUILD is used to store all of the compiled files and temporary files.

DEVELOPMENTSERVER and TESTSERVER define the URLs for the different servers. You could place this information in each build.xml file, but making changes could become very tedious. This would also not offer the degree of flexibility of the property file. Each developer can have a custom property file. The developers may use different development servers, or even be using different operating systems. The information could also be placed in the ant.bat or ant.sh file.

Each developer could have their own copy, but they would not have the ability to customize for each application. The values could also be specified on the command line, but that would be quite a bit of typing. The basic reasoning behind the property file is to allow us to customize based on differences in development environments and differences in application environments.

Building Components
The next step is to start building components. Let's start by building a JAR file for EJBOne. The first line of this example defines some basic information about the script.

 

<project name="EJBOne" default="deploy" basedir=".">
<property file="../../config.properties"/>

The default target is the target that will be run if one is not specified on the command line. We will discuss targets in greater detail a little later. The basedir defines the directory where all of the commands will execute. In this case, I placed the XML build script in the base directory. I like to do this so each component has its own build script. I check the build script into version control with the component's source code. Any developer can take the component source code, run the Ant script, and build and deploy the component. The next line includes the property file we defined in Listing 1. We will use most of these properties throughout the example.

Compiling
A target defines a unit of work. It can be specified from the command line or defined as a dependency of another target. The following code defines the target compile_ejbone:

 

<target name="compile_ejbone">
<mkdir dir="${BUILD}/ejbone"/>
<mkdir dir="${BUILD}/ejbone/META-INF"/>
<javac srcdir="${SOURCE}" destdir="${BUILD}/ejbone"
excludes="mypackage/client/**"
includes= "mypackage/common/**,
mypackage/ejbone">
<classpath>
<pathelement path="${WL_HOME}/lib/weblogic.jar"/>
</classpath>
</javac>
<copy todir="${BUILD}/ejbone/META-INF">
<fileset dir="${SOURCE}/mypackage/ejbone/META-INF">
<include name="*.xml"/>
</fileset>
</copy>
</target>

The compile target is responsible for compiling the classes for the EJBOne. First, we call mkdir to create the necessary directories. Remember that the commands are operating-system independent, so this script should work in any environment. After creating the directories, we are ready to compile some code.

We invoke the javac compiler by calling the Ant task javac. The javac task allows us to selectively choose which packages and Java classes to compile. If the includes property is not specified, all files in the source directory will be compiled. The excludes property allows the removal of specific Java files and packages.

In this case, we need to compile all of the classes in package mypackage.common and mypackage. ejbone, except the class ExtraClass and the package mypackage/ejbone/notneeded. We define the class path to ensure we compile with the correct WLS version. Finally, we copy the deployment descriptors into the build directory so they can be jarred together.

Building a JAR
The next step is to build the JAR file for the EJB. The following code uses the Ant core task JAR to build the preliminary JAR file containing the compiled classes and deployment descriptors.

 

<target name="jar_ejbone" depends="compile_ejbone">
<jar jarfile="${BUILD}/_ejbone.jar"
basedir="${BUILD}/ejbone"/>
</target>

The jar_ejbone target depends on the compile_ejbone target. We can't create the JAR file until we compile the classes. When the jar_ejbone target is called, it ensures the compile_ejbone target is called first. If the compile_ejbone target has not been executed, it will automatically execute before executing the jar_ejbone target.

Running EJBC
The XML in the following code demonstrates how to integrate ejbc with Ant. This target has two dependencies, jar_ejbone and compile_ejbone. The order of the dependencies is not important because jar_ejbone can never be executed before compile_ejbone. jar_ejbone will not be executed twice, even though it's listed as a dependency for two targets.

 

<target name="ejbc_ejbone" depends="jar_ejbone,
compile_ejbone">
<java classname="weblogic.ejbc" fork="yes"
failonerror="yes">
<sysproperty key="weblogic.home"
value="${WL_HOME}"/>
<arg line="-compiler javac ${BUILD}/_ejbone.jar
${STAGING}/ejbone.jar -keepgenerated"/>
<classpath>
<pathelement path="${WL_HOME}/lib/weblogic.jar"/>
</classpath>
</java>
</target>

Target ejbc_ejbone calls the java task. This task, as you can probably guess, executes Java applications. The Java application, in this case, is weblogic. ejbc. Fork launches a new vm, and failonerror does exactly that. If the ejbc compile process fails, the build will fail and stop. The failonerror property can only be set to yes if the fork property is also set to yes. Sysproperty allows us to specify properties to ejbc. Next we specify the command line parameters for ejbc. And finally we define the class path.

Deploying
Now that we have created our EJB JAR file, let's deploy it. The update_ejbone target shown below looks almost identical to the ejbc_ejbone target, except we run weblogic.deploy.

 

<target name="update_ejbone"
depends="ejbc_ejbone,jar_ejbone,compile_ejbone">
<java classname="weblogic.deploy"
fork="yes" failonerror="yes">
<sysproperty key="weblogic.home"
value="${WL_HOME}"/>
<arg line="-url ${DEVELOPMENTSERVER}
update mypassword ejbone ${STAGING}/ejbone.jar"/>
<classpath>
<pathelement path="${WL_HOME}/lib/weblogic.jar"/>
</classpath>
</java>
</target>

The argument line for weblogic.deploy is very interesting. First, we use the DEVELOPMENTSERVER parameter from the config.para-meter file; this will set the deployment URL to our predefined development server.

Next, we specify the action for weblogic.deploy to perform. The next parameter is the password; since we didn't specify a user name, it defaults to "system." It's not always a great idea to hard code the system password. Later we will examine a better solution.

Finally we specify the component name and the component location. Now if we type c:\Ant update_ejbone, EJBOne will be compiled, JARred, ejbc compiled, and deployed to the development server. The component will be deployed to the staging directory, not the application directory. If you have previously installed the same component to the application directory, you should remove it.

Additionally, this example demonstrates how to update an already deployed component. Creating a target that installs a new component is a very similar process. I chose to demonstrate the update because I often deploy the same components, but very rarely create entirely new components.

Building a WAR
Now that we have taken care of our EJB, let's create a WAR file. The copy and compile targets in Listing 1 ensure that everything required to build the WAR file ends up in the build/war directory. Ant has a predefined task called war that is used in the war target. We could use the jar task, but the war task makes sure everything ends up in the correct directory. The webxml property allows us to set the location of the web.xml deployment descriptor, but the war task was not made specifically for WebLogic, so we must manually include the weblogic.xml file. The webinf property allows us to define additional files that belong in the WEB-INF directory of the WAR file. Here we include the weblogic.xml deployment descriptor. Next we define where the classes are located by setting the classes property. And finally the fileset property is used to add the HTML, images and JSP files.

Easing Deployment of Large Applications
What if there is a need to deploy all of our components at one time? It would be tedious to run each build.xml script separately. We can create one Ant build script that runs all of the Ant build scripts for our application. Listing 2 shows the master build.xml script. This script will be the script that manages all of the scripts in the application. I define the target "all," which has no functionality of its own. Its only purpose is to invoke its dependencies. The ejbone, ejbtwo, and war targets use the ant task to call another build script. This allows us to control all of the build scripts within our project from the master script. The master build script will be placed in the root source directory. By typing "ant" in that directory, all three of the components will be deployed. Typing c:\> ant ejbone war will deploy only EJBOne and the WAR file.

The next target in the master build file is "ear." This target builds an EAR file and deploys it to the development server. This time, when we call the other build.xml scripts, we specify the ejbc and war targets, because we don't want to deploy them as individual components.

Next, we copy the application.xml into the META-INF directory, and JAR everything together into the EAR. The next step in the target is the deployment. The deployment has been changed by adding the ${password} parameter. Now the password is no longer hard-coded into the script. When running the script, simply type c:\ant ear -Dpassword=yourpasswordhere, and the password is passed in from the command line.

Notice, when we call weblogic.deploy, we use the "update." This will only update a component that is already deployed. We could add an additional target for new deployments or add targets that deploy to different servers. We could even add targets that deploy logical groups of components. The master build file adds an incredible amount of flexibility.

Conclusion
Now that you know how to use Ant to build and deploy WAR, EJB, and EAR files to WLS, and how to use a master build script to manage your project, you can see how the master build script can be adapted to meet the unique challenges of your project. This is just a sample of what Ant can do to improve your development process.

When implementing Ant for your project, you should consider creating a clean target for each build.xml file. The clean target would be responsible for removing any files generated by the build.xml file. Common parts of the EJB build.xml file can be moved to the master build script, although I strongly recommend leaving the compilation and building of the JAR file in a separate build.xml for each EJB.

Try integrating Ant with your version control system. Remember, the more repetitive tasks we automate, the more time we can spend developing software.

More Stories By Michael Gendelman

Michael Gendelman is a senior analyst with Biatech, Inc., a New Jersey consulting firm. He develops enterprise systems as a contractor for the US Army at CECOM Software engineering Center. Mike has been developing distributive systems for five years utilizing DCOM, CORBA, and EJB, and is a Java Certified Programmer.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.