ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Developing for the Web with Ant, Part 2
Pages: 1, 2

Deploying to Tomcat

Tomcat (available from http://jakarta.apache.org/tomcat/), the reference Web server for servlets and JSP, has become more attractive to Ant developers since it comes with custom Ant tasks for deployment. Copy the file server/lib/catalina-ant.jar from your Tomcat 5 installation into the lib directory of your Ant installation to use these tasks.



The Tomcat deployment tasks are deploy, reload, and undeploy; to use them, add these taskdef elements (discussed in Chapter 11) to your build file:

<taskdef name="deploy" classname="org.apache.catalina.ant.DeployTask"/>

<taskdef name="reload" classname="org.apache.catalina.ant.ReloadTask"/>
<taskdef name="undeploy" classname="org.apache.catalina.ant.UndeployTask"/>

To use these tasks, you'll need manager privileges with Tomcat; edit conf/tomcat-users.xml to add manager privileges for a username (admin here) and password like this:

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="manager"/>
  <role rolename="role1"/>
  <role rolename="tomcat"/>

  <user username="admin" password="password" roles="manager"/>
  <user username="role1" password="tomcat" roles="role1"/>

  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>

</tomcat-users>

You can use the deploy task to deploy a web application to Tomcat from Ant like this:

<target name="install">

    <deploy url="${manager.url}"

        username="${manager.username}"
        password="${manager.password}"         path="${app.path}"
        localWar="file://${build}"/>

</target>

Here, manager.url is the URL of the Tomcat manager servlet. The default name for this servlet is "manager", so this is something like http://localhost:8080/manager. The app.path property holds the context path at which this application should be deployed (usually / plus the name of the application as you want to use it in the URL to access the application online). The build property holds the location at which you build the Web application as it should be installed in the Tomcat webapps directory.

If you have installed an application and want Tomcat to recognize you have updated Java classes, use the reload task instead:

<target name="reload">

    <reload url="${manager.url}"

         username="${manager.username}"
         password="${manager.password}"
         path="${app.path}"/>

 </target>

To remove a Web application, use the undeploy task:

<target name="remove">

    <undeploy url="${manager.url}"
        username="${manager.username}"

        password="${manager.password}"
        path="${app.path}"/>

</target>

Deploying to Tomcat

More often than not, you won't be developing your applications on the same server you want to deploy to. You can deploy to a Tomcat installation running on a remote server by contacting the Tomcat manager servlet via URL in a browser. To do that in Ant you use the get task, which gets a file when you pass it a URL. If you're using Java 1.4 or later, this task supports any URL schema, including http:, ftp:, jar:, and https:. This task is great if you want to download online content, or, as in this case, issue commands via URLs to online code.

Before getting to deployment, here's an example that uses get to retrieve the Ant home page and stores it in ant.html:

<get src="http://ant.apache.org/" dest="ant.html"/>

You can upload Web applications to Tomcat using the manager servlet, passing the local location of the Web application to upload. For example, to upload a Web application from C:/ant/ch08/app in Windows, you'd use this location:

file:////C:\ant\ch08\app/

To upload a .war file, you add an ! at the end of the location to indicate you're uploading a file, not the contents of a directory, like this in Unix:

jar:file://///ant/ch08/app.war!/

Example 8-3 shows how this works in practice. In this case, the build file deploys a Web application from C:\ant\deploy\app that consists of a servlet (org.antbook.ch08.Deploy) that displays the message "Project Deployment!" to Tomcat. Here's the URL you pass to the get task to tell the Tomcat manager servlet what you want to do:

http://localhost:8080/manager/deploy?path=/deployment&amp;
   war=file:////c:\ant\deploy\app/

You can see this at work in Example 8-4.

Example 8-4. Deploying with get (ch08/get/build.xml)
<?xml version="1.0" encoding="UTF-8" ?>

<project default="main" basedir=".">
    <property name="tomcat.port" value="8080" />   
	<property name="tomcat.username" value="admin" />   
	<property name="tomcat.password" value="password" />   
	<target name="main" >

    <get src="http://localhost:8080/manager/deploy?path=/deployment&amp;
	war=file:////c:\ant\deploy\app/"
      dest="deploy.txt"
      username="${tomcat.username}"
      password="${tomcat.password}" />

  </target>
    </project>

Here's what the build file looks like in action:

%ant
Buildfile: build.xml

main:
      [get] Getting: http://localhost:8080/manager/deploy?
	     path=/deployment&war=file:////c:\ant\ch08\get\app/

BUILD SUCCESSFUL
Total time: 1 second

Here's what Tomcat wrote to the output file, deploy.txt:

OK - Deployed application at context path /deployment

After deployment, navigating to http://localhost:8080/deployment/org.antbook.ch08.Deploy shows the deployed servlet, as seen in Figure 8-1.


Figure 8-1. Deploying to Tomcat

TIP: For more information on using the Tomcat manager servlet, look at manager/html-manager-howto.html in your Tomcat installation.

The attributes of the get task appear in Table 8-4.

Table 8-4. The get task's attributes

Attribute

Description

Required

Default

dest

Specifies the file where you want to store the retrieved data.

Yes

ignoreerrors

Specifies you want to only log errors instead of treating them as fatal.

No

false

password

Specifies the password to use when connecting.

If username is set.

src

Specifies the URL where the data you want is.

Yes

username

Specifies the username for BASIC http authentication.

If password is set.

usetimestamp

Specifies you want to download a file only after checking the timestamp of the local copy to ensure you don't overwrite a more recent version.

No

false

verbose

Specifies you want to see full information as this task executes. Set to true/false.

No

false

TIP: When the verbose option is on, this task will display a dot (.) for every 100 KB received.

Compiling JSPs

When deploying to servers, the jspc task can be useful. This task runs the JavaServer Pages compiler and turns JSP pages into Java source, which you can compile with the javac task. Compiling JSP pages supports fast invocation of JSP pages, deployment on servers without the complete JDK, or lets you check the syntax of pages without deploying them. By default, this task uses the Jasper JSP compiler, which comes with Tomcat. Copy Tomcat's jasper-compiler.jar and jasper-runtime.jar files into the Ant lib directory to use this task. You'll need servlet.jar, which comes with Tomcat, in the Ant lib directory.

For example, say you have this JSP page, greeting.jsp:

<HTML>
  <HEAD>
    <TITLE>Creating a Greeting</TITLE>
  </HEAD>

  <BODY>
    <H1>Creating a Greeting</H1>
    <%
        out.println("Hello from JSP!");    //Display the greeting
     %>
  </BODY>

</HTML>

Example 8-5 shows how to compile this JSP into greeting.java.

Example 8-5. Compiling JSP pages (ch08/jspc/build.xml)
<?xml version="1.0" ?>

<project default="main">

    <property name="message" value="Compiling the JSP...." />
    <property name="src" location="source" />

    <property name="output" location="bin" />

    <target name="main" depends="init, compile">

        <echo>
            ${message}
        </echo>
    </target>
      <target name="init">
        <mkdir dir="${output}" />

    </target>
      <target name="compile">
        <jspc srcdir="${src}"
            destdir="${output}"
            package="org.antbook.jsp"

            verbose="9">
            <include name="**/*.jsp" />
        </jspc>
    </target>
  </project>

Here's what you see when you run the build file:

%ant
Buildfile: build.xml

init:

compile:
     [jspc] Compiling 1 source file to 
    /home/steven/ant/ch08/jspc/bin/org/antbook/jsp
  [jasperc] 2004-06-30 02:20:09 - Class name is: greeting
  [jasperc] 2004-06-30 02:20:09 - Java filename is: 
    /home/steven/ant/ch08/jspc/bin/org/antbook/jsp/greeting.java
  [jasperc] 2004-06-30 02:20:09 - Accepted 
    org.apache.jasper.compiler.Parser$Scriptlet at /greeting.jsp(7,4)
  [jasperc] 2004-06-30 02:20:09 - Compiling with: -encoding UTF8 

main:
     [echo]
     [echo]             Compiling the JSP....
     [echo]

BUILD SUCCESSFUL
Total time: 3 seconds

And this is what the resulting Java code, greeting.java, looks like:

package org.antbook.jsp.;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;


public class greeting extends HttpJspBase {

    static {
    }
    public greeting( ) {
    }

    private static boolean _jspx_inited = false;

    public final void _jspx_init( ) 
	   throws org.apache.jasper.runtime.JspException {
    }

    public void _jspService(HttpServletRequest request, HttpServletResponse  
        response)
        throws java.io.IOException, ServletException {

        JspFactory _jspxFactory = null;
        PageContext pageContext = null;
        HttpSession session = null;
        .
        .
        .
        out.println("Hello from JSP!");    //Display the greeting
        .
        .
        .
    }
}

Here's another example, which compiles JSP pages, checks the dependencies, and uses the javac task to create the actual bytecode for this JSP:

<jspc
    destdir="temp"
    srcdir="${src}"
    package="org.antbook.ch08">

    <include name="**/*.jsp" />
</jspc>

<depend
    srcdir="temp"
    destdir="${bin}"
    classpath="lib/app.jar"/>

<javac
    srcdir="temp"
    destdir="${bin}"
    classpath="lib/app.jar" />

You can see the attributes of the jspc task in Table 8-5.

Table 8-5. The jspc task's attributes

Attribute

Description

Required

Default

classpath

Specifies the classpath to use when you're running the JSP compiler. You can specify this by nested classpath elements.

No

classpathref

Specifies the classpath to use when you're running the JSP compiler, by reference.

No

compiler

Specifies the classname of a JSP compiler, such as jasper or jasper42.

No

jasper

compilerclasspath

Specifies the classpath that should be used to find the compiler specified by the compiler attribute.

No

destdir

Specifies where you want to place the compiled files.

Yes

failonerror

Specifies if the task to fail if it encounters an error.

No

yes

ieplugin

Specifies the Java Plugin class ID for Internet Explorer.

No

mapped

Specifies you want to generate separate write statements for each HTML line in the JSP. Set to true/false.

No

package

Specifies the name of the destination package for the generated compiled classes.

No

srcdir

Specifies where you want the task to look for source JSP files.

Yes

uribase

Specifies the base URI for relative URI references in JSP pages.

No

uriroot

Sets the root directory from which URIs should be resolved.

No

verbose

Specifies you want full (verbose) output. Set to an integer value (0-9).

No

0

webinc

Specifies the filename for the section of web.xml that details any servlets.

No

webxml

Specifies the filename for the generated web.xml-type file.

No

The jspc task is a directory-based task, so the JSP files to be compiled are located the same way as the javac task locates files, which means you can use nested elements, such as includes and excludes. You can use nested classpath and classpathref elements, as well as nested webapp elements. The webapp element, unique to the jspc task, instructs the JSP compiler to build an entire Web application. The one attribute of the webapp element is the basedir attribute, which sets the base directory of the application. The base directory must have a WEB-INF subdirectory beneath it. If you use this element, the task uses the compiler for all dependency checking. Here's an example using webapp:

<jspc
    package="org.antbook.ch08">
    <include name="**/*.jsp" />

    <webapp basedir="${ch08}" />
</jspc>

Deploying to EJB Containers

Fundamentally, deploying to Enterprise JavaBean (EJB) application servers is similar to other Ant deployment projects you've seen. You can use the tasks covered to package and deploy EJB applications. For example, you can see a build file developed for the JBoss server in Example 8-6; this build file first creates a .war file and then packages it into an .ear file for deployment.

Example 8-6. A Jboss EJB build (ch08/ejb/build.xml)
<?xml version="1.0" ?>
<project default="main" basedir=".">

    <target name="main" depends="init, compile, war, ear"/>

    <target name="init">
        <property name="src" value="${basedir}/src"/>

        <property name="bin" value="${basedir}/output"/>
        <property name="web" value="${basedir}/web"/>
        <property name="descriptors"             
		   value="${basedir}/output/deploymentdescriptors"/>

        <property name="eardir" value="${basedir}/output/ear"/>
        <property name="wardir" value="${basedir}/output/war"/>
        <property name="warfile" value="app.war"/>

        <property name="earfile" value="app.ear"/>
            <mkdir dir="${wardir}/WEB-INF"/>
        <mkdir dir="${wardir}/WEB-INF/classes"/>

        <mkdir dir="${eardir}/META-INF"/>
    </target>
        <target name="compile">
        <javac destdir="${bin}" srcdir="${src}" includes="**/*.java" />

    </target>
        <target name="war">
        <copy todir="${wardir}">
            <fileset dir="${web}" includes="**/*.*" />         </copy>

            <copy file="${descriptors}/web.xml" todir="${wardir}/WEB-INF" />
            <copy todir="${wardir}/WEB-INF/classes">
            <fileset dir="${bin}" includes="**/*.class" />         </copy>

        <jar jarfile="${eardir}/${warfile}" basedir="${wardir}" />
    </target>

    <target name="ear">

        <copy file="${descriptors}/application.xml" 
		   todir="${eardir}/META-INF" />
            <jar jarfile="${basedir}/${earfile}" basedir="${eardir}" />

    </target>
    </project>

That's all it takes. Though this build file gets the job done using standard Ant tasks, tasks built into Ant make it easier to work with EJB applications, starting with the ear task.

Creating EAR Files

The ear task is handy for creating .ear files and makes special provisions for the application.xml file needed in most EARs. It's not mandatory to use this task to create a .ear file, but it can make life easier. You can see the attributes of this task in Table 8-6.

TIP: The ear task is an extension of the Jar task with special treatment for application.xml. You can perform the same operation by using the prefix and fullpath attributes of zipfilesets in a zip or jar task.

Table 8-6. The ear task's attributes

Attribute

Description

Required

Default

appxml

Specifies the deployment descriptor you want to use, such as application.xml.

Yes, unless update is set to true.

basedir

Specifies the directory from which to get the files.

No

compress

Indicates you want to not only store data but compress it.

No

true

defaultexcludes

Specifies if you want to use default excludes or not. Set to yes/no.

No

Default excludes are used.

destfile

Specifies the EAR file you want to create.

Yes

duplicate

Specifies what to do if a duplicate file is found. Valid values are add, preserve, and fail.

No

add

encoding

Specifies the character encoding to use for filenames in the EAR file.

No

UTF8

excludes

Specifies the patterns matching files to exclude, as a comma- or space-separated list.

No

excludesfile

Specifies the name of a file where each line is a pattern matching files to exclude.

No

filesonly

Specifies you want to store only file entries.

No

false

includes

Specifies the patterns matching files to include, as a comma- or space-separated list.

No

includesfile

Specifies the name of a file where each line is a pattern matching files to include.

No

keepcompression

Preserves the compression as it has been in archives you're compressing instead of using the compress attribute. Available since Ant 1.6.

No

manifest

Specifies the manifest file to use in the compressed file.

No

update

Specifies whether you want to update or overwrite the target file if it exists.

No

false

The extended zipfileset element from the zip task, which supports the attributes prefix, fullpath, and src, is available in the ear task. The nested metainf element specifies a fileset; all files included in this fileset will end up in the META-INF directory of the .ear file.

This task lets you specify where to get application.xml from, using the appxml attribute. Here's an example that creates an .ear file:

<ear destfile="${output}/app.ear" appxml="${src}/application.xml">

    <fileset dir="${wardir}" includes="*.war"/>
</ear>

Supporting Hot Deployment

The serverdeploy task is designed to support hot deployment (where you don't have to take the server down before deploying) to EJB-aware servers. You set the action attribute to values you've seen, like those used for the Tomcat manager servlet: "deploy", "delete", and "undeploy".

TIP: You'll need vendor-specific deployment software to make this one work. Ant provides the build-end, but your server will need to provide a deployment facility that Ant can connect and interact with.

As of this writing, this task only supports Weblogic servers and the JOnAS 2.4 Open Source EJB server, but support for other EJB containers should be added soon. This task has only two attributes, which appear in Table 8-7, and requires some nested elements.

Table 8-7. The serverdeploy task's attributes

Attribute

Description

Required

action

Specifies the action you want to perform, such as deploy, delete, list, undeploy, or update.

Yes

source

Specifies the path and filename of the component you want to deploy. This may be an .ear, .jar, .war, or other file type supported by the server.

Depends on the server.

The serverdeploy task supports a nested classpath element to set the classpath. It supports the vendor-specific generic, jonas, and weblogic nested elements.

The generic element

This is the element you use for generic Java-based deployment if you've got deployment codea Java classsupplied by the server's vendor. If there's a vendor-specific element for serverdeploy, use that, of course, but if not, try the generic element. The attributes of this element appear in Table 8-8.

Table 8-8. The generic element's attributes

Attribute

Description

Required

classname

Specifies the classname of the deployment tool you want to run.

Yes

classpath

Specifies the classpath you want the JVM running the tool to use. May be supplied as a nested element.

Depends on the server.

password

Specifies the password you want to use on the server.

Depends on the server.

server

Specifies the URL of the server to use.

Depends on the server.

username

Specifies the username to log in with.

Depends on the server.

The generic element supports nested arg and jvmarg elements. Here's an example using the generic element for deployment that assumes the deployment tool for the target Web server is org.steven.j2ee.config.Deploy:

<serverdeploy action="deploy" source="${eardir}/app.ear">
    <generic classname="org.steven.j2ee.config.Deploy"
        classpath="${classpath}"
        username="${user.name}"

        password="${user.password}">
        <arg value="-install"/>
        <jvmarg value="-mx512m"/>
    </generic>

</serverdeploy>

The weblogic element

The weblogic element is designed to run the weblogic.deploy deployment tool; legal actions for this tool are deploy, undeploy, list, update, and delete. The attributes for this element appear in Table 8-9.

Table 8-9. The weblogic element's attributes

Attribute

Description

Required

Default

application

Specifies the name of the application you want to deploy.

Yes

classpath

Specifies the classname of the deployment tool you want to run.

No

component

Specifies the string for deployment targets, of the form: <component>:<target1>,<target2>..... In this case, component is the archive name (without a file extension).

No

debug

Specifies if you want debug information to be displayed during deployment.

No

password

Specifies the password you want to use on the server.

Yes

server

Specifies the URL of the server to use.

No

username

Specifies the username to log in with.

No

system

Here's an example using this element inside a serverdeploy element to deploy to a WebLogic server:

<serverdeploy action="deploy"     source="${eardir}/app.ear">

    <weblogic application="app"
        server="ff19://server:7001"
        classpath="${weblogic.home}/lib/weblogic.jar"
        username="${user.name}"
        password="${user.password}"

        component="appserver,productionserver" />
</serverdeploy>

The jonas element

The jonas element supports deployment to JOnAS (Java Open Applicaton Server) servers. Valid actions for the JOnAS deployment tool (org.objectweb.jonas.adm.JonasAdmin

)

are deploy, undeploy, list and update. The attributes of this element appear in Table 8-10.

Table 8-10. The jonas element's attributes

Attribute

Description

Required

Default

jonasroot

Specifies the root directory for the server.

Yes

orb

Specifies the orb, such as RMI, JEREMIE, DAVID, and so on. If the orb is DAVID (RMI/IIOP), specifies the davidhost and davidport attributes.

No

The ORB present in the classpath.

davidhost

Specifies the value for the property david.CosNaming.default_host.

No

davidport

Specifies the value for the property david.CosNaming.default_port.

No

classname

Specifies the classname of the deployment tool you want to run.

No

org.objectweb.jonas.adm.JonasAdmin

classpath

Specifies the classpath you want the JVM running the tool to use. May be supplied as a nested element.

No

server

Specifies the URL of the server to use.

Yes

TIP: If you want to build in delay times to take into account delays in getting responses from a server, use the Ant waitfor task. You can use the sleep task for this purpose.

The jonas element supports nested classpath, arg, and jvmarg elements. Here's an example using serverdeploy to deploy to a JOnAS server:

<serverdeploy action="deploy" source="${eardir}/app.jar">
    <jonas server="JOnAS5" jonasroot="${jonas.root}">
        <classpath>

            <pathelement path="${jonas.root}/lib/RMI_jonas.jar"/>
        </classpath>
    </jonas>
</serverdeploy>

Steve Holzner is the author of O'Reilly's upcoming Eclipse: A Java Developer's Guide.

Return to ONJava.com.