Switch to standard view 
  Sybase logo
 
 
 



J2EE Application Deployment to EAS Using ANT

This document summarizes the process used at Hennepin County to deploy a J2EE application developed in IBM Web Sphere Application Developer (WSAD) to Sybase Enterprise Application Server (EAS) using Apache ANT tool.

Background

The application described here is the Community Services Group Data Sharing (CSG Data Sharing) system. It consists of Web application used by the CSG staff to manage client records in the central database, and the messaging part that constantly populates the database with the information coming from different independent systems through the IBM WebSphere MQ Integrator. The messages are converted into common format by the Integrator and placed in the output queue. The receive side CSG system has to process incoming messages and update the central database. The system has one service component reading messages from the Integrator queue and publishing them to the EAS message topic. The Message Driven Bean EJBs, each for one of five different message types, are registered as listeners on the topic, and invoke other session façade EJB to process these messages.

Development team is using WSAD for programming and testing, including some testing in the Web Sphere Test Environment which is part of the studio. The application is designed with portability in mind, so it may be deployed to either server, WebSphere or EAS. The project source code is saved in the Rational ClearCase source control repository.

At the time when this project started, WSAD version 4.0 was available, which had limited Ant support, meaning it wasn?t easy to configure the tool within the studio to use it for EAS deployment. That was the reason that Ant is used as an external tool. The build script compiles source code files, packages them into JAR, WAR, and EAR files, deploys the EAR file to the EAS. It also builds JavaDoc API, and uses Java2HTML ( www.java2html.org tool to create an HTML formatted view for the project Java source code. The process may be extended to include checking in and out files from a source control repository, running JUnit tests after deployment to integration server. The same process may be useful for a scheduled build where the development studio is not required at all.

Setup

The setup pretty much follows EAS System Administration Guide, Chapter 12 Using jagtool and jagant. The EAS development server is installed in the same workstation as the WSAD. Although deployment to a remote server is used as well. The Ant is installed in D:\jakarta-ant-1.5, and ANT_HOME environment variable set to point to this directory. The tool is run using %JAGUAR%\bin\jagant.bat script from a command prompt. The script sets CLASSPATH and invokes the default JVM at
C:\Program Files\Sybase\Shared\Sun\jdk\jdk1.3

The application workspace is located in the ClearCase view subdirectory, and has these separate projects in it:

  1. J2EE project
  2. EJB project
  3. Web project
  4. Common classes Java project. The project is for developing EJB client view classes that are common for EJB layer and web application.
  5. Test Java project that contains various JUnit tests.

The project workspace structure looks like this:


ClearCase view folder
     |_ . . .

|_ . . . other view content, documentation, model etc.

|_ . . .

|_ source folder

|_ WSAD_workspace

|_ J2EE Project

|      . . .

|      CommonClasses.jar

|_META-INF

     application.xml

        |_ Common Project

             |_ bin

             |_ src

|_ EJB Project

     |_ ejbModule

          . . .

          |_ META-INF

               ejb-jar.xml

|_ Web Project

     |_ Java Source

     |_ Web Content

          . . .

          |_ WEB-INF

               |_ classes

               |_ lib

               web.xml

|_ Test and build Project

     |_ lib

     |_ bin

     |_ src      (JUnit tests source)

     build.xml

     build.properties

     builddefault.properties

     buildversion.properties

     jagtasks.xml

     build.bat

The Test and build Project is used for the JUnit tests as well as for running the ANT build script.

The following files are placed in this project directory:

<?xml version = "1.0" ?>

<!DOCTYPE project [ <!ENTITY jagtasks SYSTEM "jagtasks.xml"> ] >

<project default = "gendtd" basedir = "." >

    <!-- include Jaguar task definitions -->

    &jagtasks;

   <target name = "gendtd" >

        <antstructure output = "project.dtd" />

    </target>

</project>

Assuming the above script was saved in the file antstructure.xml, it can be run by this command that will produce the project.dtd file in the current directory:

D:\>jagant -buildfile antstructure.xml

  • build.bat file simplifies running the jagant.bat . The file has this command in it:

    D:\<ClearCase view>\srs\WSAD_workspace\CSGTest\>
                  jagant -buildfile deploy.xml
                         -logfile deploy.log deploy


    The ? deploy? is the default build target, it compiles source files, and builds JAR, WAR and EAR archives, then deploys the EAR file to a specified EAS. To run other targets in the same script, change ?deploy? to the target name. For instance, to generate JavaDoc API, change it to ? apidoc?, to add generate Java2HTML files use   ? j2html? target. To run all targets use ? all? or ? publish?. For details see Deployment Script section below.

    Building and deploying application

    There are these points that have to be considered when deploying the application.

    1. The script handles project that have these modules:

      • Common classes JAR file
      • Web module as WAR file
      • EJB project as JAR file

      Any of these modules can be omitted by commenting out corresponding project name in the default build properties file, so the application may have only Web part, or only EJB part, or both. The common classes module is optional in any case.

      The common classes Java project is a collection of classes that are part of the component remote interface method signatures, so they have to be deployed to both, EJB and Web containers. Keeping these classes in a separate JAR simplifies deployment of the web application when it?s deployed to a separate server, Tomcat for instance. These classes must be present on the CLASSPATH during deployment in order to compile component stubs. This is done if the common JAR file is included in the manifest of every module that requires it. When working with the WSAD it is done by including it in the list of dependant JAR files in the Web and EJB project properties. The build script does not modify manifest files, instead it just uses the files as they are maintained by the studio.

    2. EAR deployment overrides all EAS specific EJB component settings modified in Jaguar Manager. It doesn?t change any property modifications done to the CORBA service component that is part of the same package. Therefore after the initial deployment, all EAS specific settings are done in the Jaguar Manager, and the application is exported using Jaguar Manager commands Export J2EE EAR, Export EJB JAR, and Export J2EE WAR, with ?Export with EAServer XML configuration file? options selected. Then the sybase-easerver-config.xml file is extracted from each exported archive and placed in the appropriate WSAD project META-INF directory. This way when the EAR file is deployed, EAS component property changes are applied based on these configuration files.
      The deployment script below includes the target that exports these three configuration files, but the CSGDataMAtchingEJB package configuration file doesn?t have all the component settings in it, so it is exported manually at this time.

    3. The CSG project also has a CORBA Java component that is developed in the EJB project and is part of the same package as the EJB. When deploying the EAR file the new component implementation is deployed as well, but the component properties if they were cofigured using Jaguar Manager, are not changed. The script below has deploy.with.service target that will check if the component exists or not on the server, and if it doesn?t, then the component will be deployed using properties file that is defined in the build properties.

    4. When the web application is in use, or has been in use after the server last restart, then JAR files in the WEB-INF\lib directory are locked (we are using EAS 4.1), and deployment fails. To avoid that we put server in the ?admin? mode before the deployment, and set to ?ready? mode after the deployment is finished.

    The application initial deployment is done in these steps:

  • Run build and deployment script.
  • Configure application components server specific properties in Jaguar Manager: set data source links, resource references, security etc.
  • Export sybase-easerver-config.xml files to the WSAD corresponding project META-INF directories.

    After that repeat deployments are done just by running the deployment script.

    The script default properties

    The default properties file is used by the project team, and each developer can create a local build.properties file that overrides any of the default. For instance the workspace location may be different for each developer.

    Listing 1.

    #####################################################################
    # Default global properties for this build
    #
    # To override create build.property file in the same directory as
    # this file, copy this file content into the new file, and modify
    # accordingly
    #
    #####################################################################

    #------------------------------------------------------------
    # Project specific properties
    #------------------------------------------------------------

    project.name          = < project name as it would appear in the EAR file name prefix>
    project.version     = 1.00
    project.j2ee.name    = < WSAD J2EE project name >
    project.ejb.name     = < WSAD EJB project name >
    project.web.name     = < WSAD Web project name >
    project.common.name = < WSAD Common classes Java project name >
    project.test.name    = < WSAD Test and build Java project name >
    project.webapp.name = < Web application context path >

    project.path        = < WSAD workspace path>
    archive.dir           = < Project distribution directory for EAR file, JavaDoc, and Java2HTML files>
    javadoc.packages    = hennepin.co.*

    #------------------------------------------------------------
    # optionaly install a CORBA service component if it is missing
    # comment out the next two lines if project doesn't use a
    # service component, and use "deploy" target instead of
    # "deploy.with.service"
    #------------------------------------------------------------

    service.comp.name           = ${project.ejb.name}/QCopy
    service.comp.props.file        = ${ejb.src.dir}/META-INF/${service.comp.name}.props

    #------------------------------------------------------------
    # EAS connection
    #------------------------------------------------------------

    jaguar.host          = localhost
    jaguar.port          = 9000
    jaguar.user          = jagadmin
    jaguar.password     =

    #------------------------------------------------------------
    # workspace directories reflect usual WSAD workspace structure
    #------------------------------------------------------------

    project.j2ee.path    = ${project.path}/${project.j2ee.name}
    project.ejb.path     = ${project.path}/${project.ejb.name}
    project.web.path     = ${project.path}/${project.web.name}
    project.common.path = ${project.path}/${project.common.name}
    project.test.path    = ${project.path}/${project.test.name}

    lib.dir               = ${project.test.path}/lib

    ear.dir               = ${project.j2ee.path}


    ejb.dir               = ${project.ejb.path}
    ejb.src.dir           = ${ejb.dir}/ejbModule
    ejb.build.dir        = ${ejb.dir}/ejbModule

    war.dir               = ${project.web.path}
    war.src.dir           = ${war.dir}/Java Source
    war.jsp.dir           = ${war.dir}/Web Content
    war.lib.dir           = ${war.dir}/Web Content/WEB-INF/lib
    war.build.dir        = ${war.dir}/Web Content/WEB-INF/classes

    common.dir            = ${project.common.path}
    common.src.dir       = ${project.common.path}/src
    common.build.dir     = ${project.common.path}/bin

    distrib.dir           = ${project.path}/dist
    api.dir               = ${distrib.dir}/api
    api.src               = ${distrib.dir}/src
    j2html.dir            = ${distrib.dir}/j2html
    api.publish.dir      = ${archive.dir}/api
    j2html.publish.dir   = ${archive.dir}/j2html

    #------------------------------------------------------------
    # Java compiler options
    #------------------------------------------------------------

    compiler.type        = modern
    compiler.deprecation= on
    compiler.debug       = off
    compiler.optimize    = on
    compiler.verbose     = off

    #------------------------------------------------------------
    # Javadoc options.
    #------------------------------------------------------------

    javadoc.author       = true
    javadoc.private     = true
    javadoc.use          = true
    javadoc.version     = true


    The build script

    The deployment script build.xml content listed below (see Listing 2.)includes comments to make it self-explanatory.

    Listing 2.

    <?xml version = "1.0" ?>

    <!DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "project.dtd" [

        <!ENTITY jagtasks SYSTEM "jagtasks.xml">

    ] >

    <!-- ======================================================================= -->
    <!?- Build and deploy EAR to EAS                                              -->
    <!--                                                                          -->
    <!-- Properties for this build are in the builddefault.properties file, to    -->
    <!-- override create build.property file in the same directory, copy          -->
    <!-- properties you want to override from bulddefault.properties into the     -->
    <!-- the new file and modify accordingly.                                     -->
    <!--                                                                          -->
    <!-- Author: Yuriy Natarius                                                   -->
    <!--                                                                          -->
    <!-- ======================================================================= -->

    <project default = "deploy" basedir = "." >

           <description> Build and deploy J2EE application to EAS, generate JavaDoc and java2HTML files. </description>

    <target name = "antstructure" description = "Run this target to generate project.dtd including EAS tasks. Use the DTD with your XML editor" >

                  <antstructure output = "project.dtd" />

           </target>

           <!-- include Jaguar task definitions -->

           &jagtasks;

           <!--============= Properties for this build =======-->

           <property file = "build.properties" />
           <property file = "builddefault.properties" />
           <property file = "buildversion.properties" />

           <!--============= All ============================-->
           <target name = "all" description = "build and deploy EAR file" >
                  <echo> ************************************************************** </echo>
                  <echo> Full build, deploy, doc, publish </echo>
                  <echo> -------------------------------- </echo>
                  <echo> for partial buld use these tragets: </echo>
                  <echo> deploy to deploy EAR file only </echo>
                  <echo> deploy.with.service to deploy service component as well </echo>
                  <echo> apidoc to generate JavaDOC API </echo>
                  <echo> j2html to generate java2HTML source view </echo>
                  <echo> publish same as this "all" target </echo>
                  <echo> ************************************************************** </echo>
                  <antcall target = "publish" />
           </target>

           <!--============= Init ============================-->
           <target name = "init" description = "Initialize project class path" >
                  <tstamp>
                         <format property = "DSTAMP" pattern = "MM-dd-yyyy" />
                         <format property = "TSTAMP" pattern = "h:mm:ss a" />
                  </tstamp>
                  <echo message = "${DSTAMP} ${TSTAMP}" ></echo>
                  <echo> ******************************************************** </echo>
                  <echo> setting project class path </echo>
                  <echo> ******************************************************** </echo>
                  <path id = "project.class.path" >
                         <fileset dir = "${lib.dir}" includes = "*.jar" />
                         <fileset dir = "${ear.dir}" includes = "*.jar" />
                         <fileset dir = "${war.lib.dir}" includes = "*.jar" />
                  </path>
                  <echo />

                  <echo> ******************************************************** </echo>
                  <echo> deleting existing classes </echo>
                  <echo> ******************************************************** </echo>
                  <delete quiet = "false" failonerror = "false" >
                         <fileset dir = "${common.build.dir}" includes = "**/*.class" />
                         <fileset dir = "${ejb.build.dir}" includes = "**/*.class" />
                         <fileset dir = "${war.build.dir}" includes = "**/*.class" />
                  </delete>
                  <delete dir = "${distrib.dir}" />
                  <mkdir dir = "${distrib.dir}" />
           </target>

           <!--============= Build ============================-->
           <!-- build new common jar file                       -->
           <target name = "build.common.jar" depends = "init" if = "project.common.name"                               description = "Compile and build common classes JAR file" >
                  <echo> ******************************************************** </echo>
                  <echo> compile and build common files JAR file </echo>
                  <echo> ******************************************************** </echo>
                  <javac srcdir = "${common.src.dir}" destdir = "${common.build.dir}"                                      
    debug = "${compiler.debug}" compiler = "${compiler.type}"                                         optimize = "${compiler.optimize}" deprecation = "${compiler.deprecation}"                        verbose = "${compiler.verbose}" >
                         <classpath refid = "project.class.path" />
                  </javac>
                  <copy todir = "${common.build.dir}" >
                         <fileset dir = "${common.src.dir}" includes = "**/*.properties" />
                  </copy>
                  <jar basedir = "${common.build.dir}"                                                                          destfile = "${distrib.dir}/${project.common.name}.jar"                                                 includes = "**/*.class" />
                  <copy file = "${distrib.dir}/${project.common.name}.jar"                                               todir = "${project.j2ee.path}" />
           </target>

           <!-- build EJB module JAR file                       -->
           <target name = "build.ejb.jar" depends = "init, build.common.jar" if = "project.ejb.name"                    description = "Compile and build EAJB module JAR file" >
                  <echo> ******************************************************** </echo>
                  <echo> compile and build EJB module JAR file </echo>
                  <echo> ******************************************************** </echo>
                  <javac srcdir = "${ejb.src.dir}" destdir = "${ejb.build.dir}"  
     
                   
    debug = "${compiler.debug}" compiler = "${compiler.type}"
     
                 
    optimize = "${compiler.optimize}" deprecation = "${compiler.deprecation}"
                     
    verbose = "${compiler.verbose}" excludes = "**/_*.java,
    **/EJS*.java,**/Concrete*.java,                                                                **/websphere_deploy/**/*.java"
    >

                         <classpath refid = "project.class.path" />
                  </javac>
                  <copy todir = "${ejb.build.dir}" >
                         <fileset dir = "${ejb.src.dir}" includes = "**/*.properties" />
                  </copy>
                  <jar destfile = "${distrib.dir}/${project.ejb.name}.jar"                                                     manifest = "${ejb.build.dir}/META-INF/MANIFEST.MF" >
                         <fileset dir = "${ejb.build.dir}" includes = "**/*.class" />
                         <fileset dir = "${ejb.src.dir}" includes = "META-INF/*.*" />
                  </jar>
           </target>

           <!-- build web module WAR file                       -->
           <target name = "build.web.war" depends = "init, build.common.jar" description = "Compile and build web application WAR file" >
                  <echo> ******************************************************** </echo>
                  <echo> compile and build Web module WAR file </echo>
                  <echo> ******************************************************** </echo>
                  <javac srcdir = "${war.src.dir}" destdir = "${war.build.dir}" debug = "${compiler.debug}"  
                        compiler = "${compiler.type}" optimize = "${compiler.optimize}"
     
                      
    deprecation = "${compiler.deprecation}" verbose = "${compiler.verbose}" >
                         <classpath refid = "project.class.path" />
                         <classpath>
                                <fileset dir = "${war.lib.dir}" includes = "*.jar" />
                         </classpath>
                  </javac>
                  <copy todir = "${war.build.dir}" >
                         <fileset dir = "${war.src.dir}" includes = "**/*.properties" />
                  </copy>
                  <jar basedir = "${war.jsp.dir}" destfile = "${distrib.dir}/${project.web.name}.war"                         manifest = "${war.jsp.dir}/META-INF/MANIFEST.MF" />
           </target>

           <!-- build J2EE module EAR file                      -->
           <target name = "build.ear" depends = "init, build.ejb.jar, build.web.war, build.counter"                           description = "Build J2EE application EAR file" >

                  <echo> ******************************************************** </echo>
                  <echo> build J2EE EAR file </echo>
                  <echo> ******************************************************** </echo>
                  <property name = "ear.name" value = "${distrib.dir}/${project.name}-${DSTAMP}-${project.version}.${build.version}.ear" />

                  <jar destfile = "${ear.name}" >

                         <fileset dir = "${distrib.dir}" includes = "${project.ejb.name}.jar" />

                         <fileset dir = "${distrib.dir}" includes = "${project.web.name}.war" />

                         <fileset dir = "${project.j2ee.path}" includes = "**/*.*" />

                  </jar>

           </target>

           <!-- create a counter -->

           <target name = "build.counter" >

                  <propertyfile file = "./buildversion.properties" >

                         <entry key = "build.version" type = "int" operation = "+" value = "1" pattern = "0000" />

                  </propertyfile>

                  <echo message = "Build counter: ${project.version}.${build.version}" />

           </target>

           <!--============= Connect to EAS ==================-->

           <target name = "connect" depends = "init" >

                  <echo> ******************************************************** </echo>

                  <echo> connecting to EAS </echo>

                  <echo> ******************************************************** </echo>

                  <jag_connect host = "${jaguar.host}" port = "${jaguar.port}" user = "${jaguar.user}"                                  password = "${jaguar.password}" />

           </target>

           <!--============= Deploy J2EE EAR file to EAS =====-->

           <target name = "deploy" depends = "connect, build.ear" >

                  <echo> ******************************************************** </echo>

                  <echo> deploy J2EE EAR file to EAS </echo>

                  <echo> ******************************************************** </echo>

                  <jag_set_admin reason = "clean up and unlock files before deploy" />

                  <jag_restart />

                  <sleep seconds = "15" />

                  <waitfor checkevery = "5" checkeveryunit = "second" maxwait = "5" maxwaitunit = "minute" >

                         <socket server = "${jaguar.host}" port = "${jaguar.port}" />

                  </waitfor>

                  <jag_deploy type = "ear" stubsandskels = "true" install = "true" strategy = "full"                                 verbose = "true" file = "${ear.name}" />

                  <jag_refresh entity = "Application:${project.j2ee.name}" />

                  <jag_set_ready />

           </target>

           <!--============= Deploy with service component ====-->

           <target name = "check.service.comp" depends = "connect" description = "Check if service component exists" >

                  <jag_exists entity = "Component:${service.comp.name}" property = "comp.exists" />

           </target>

           <target name = "deploy.with.service" depends = "check.service.comp, deploy" unless = "comp.exists"                     description = "Deploy service component" >

                  <jag_create entity = "Component:${service.comp.name}" file = "${service.comp.props.file}" />

           </target>

           <!--============= Copy source files to one location ====-->

           <target name = "makedir" depends = "init, build.ear" description = "make directories for api and j2html" >

                  <mkdir dir = "${api.dir}" />

                  <mkdir dir = "${api.src}" />

           </target>

           <target name = "copy.common.src" depends = "makedir" if = "project.common.name" description = "copy Common Java project source files for JavaDoc and java2HTML processing" >

                  <copy todir = "${api.src}" >

                         <fileset dir = "${common.src.dir}" includes = "**/*.*" />

                  </copy>

           </target>

           <target name = "copy.ejb.src" depends = "copy.common.src" if = "project.ejb.name" description = "copy EJB module source files for JavaDoc and java2HTML processing" >

                  <copy todir = "${api.src}" failonerror = "false" >

                         <fileset dir = "${ejb.src.dir}" includes = "**/*.java" excludes = "**/_*.*, **/EJS*.*" />

                  </copy>

           </target>

           <target name = "copy.src" depends = "copy.ejb.src" if = "project.web.name" description = "copy Web module source files for JavaDoc and java2HTML processing" >

                  <copy todir = "${api.src}" >

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

                  </copy>

           </target>

           <!--============= Generate JavaDoc API =============-->

           <target name = "apidoc" depends = "copy.src" >

                  <echo> ******************************************************** </echo>

                  <echo> generating JavaDOC files </echo>

                  <echo> ******************************************************** </echo>

                  <javadoc packagenames = "${javadoc.packages}" destdir = "${api.dir}"                                          author = "${javadoc.author}" version = "${javadoc.version}" use = "${javadoc.use}"                            private = "${javadoc.private}" windowtitle = "${project.name} API"                                          doctitle = "${project.name} ${project.version}"                                                                link = "http://jakarta.apache.org/struts/doc-1.0.2/api" >

                         <sourcepath>

                                <pathelement path = "${api.src}" />

                         </sourcepath>

                         <classpath refid = "project.class.path" />

                  </javadoc>

           </target>

           <!--============= Generate Java2HTML =============-->

           <target name = "j2html" description = "Creates html from java files" depends = "copy.src" >

                  <echo> ******************************************************** </echo>

                  <echo> generating java2HTML files </echo>

                  <echo> ******************************************************** </echo>

                  <mkdir dir = "${j2html.dir}" />

                  <java classname = "j2h" fork = "yes" >

                         <classpath refid = "project.class.path" />

                         <arg line = "-d   ${j2html.dir}" />

                         <arg line = "-js ${api.src}" />

                  </java>

           </target>

           <!--============= Publishing          =============-->

           <target name = "publish" depends = "deploy, apidoc, j2html" >

                  <echo> ******************************************************** </echo>

                  <echo> Publishing build files </echo>

                  <echo> ******************************************************** </echo>

                  <echo> -------- Publishing EAR file --------- </echo>

                  <copy file = "${ear.name}" todir = "${archive.dir}" />

                  <echo> -------- Publishing JavaDoc API -------- </echo>

                  <delete file = "${archive.dir}/${project.name}_API.zip" />

                  <zip basedir = "${api.dir}" destfile = "${archive.dir}/${project.name}_API.zip" />

                  <delete quiet = "true" >

                         <fileset dir = "${api.publish.dir}" includes = "**/*.*" />

                  </delete>

                  <copy todir = "${api.publish.dir}" >

                         <fileset dir = "${api.dir}" includes = "**/*.*" />

                  </copy>

                  <echo> -------- Publishing java2HTML files -------- </echo>

                  <delete quiet = "true" >

                         <fileset dir = "${j2html.publish.dir}" includes = "**/*.*" />

                  </delete>

                  <copy todir = "${j2html.publish.dir}" >

                         <fileset dir = "${j2html.dir}" includes = "**/*.*" />

                  </copy>

           </target>

    </project>

    Credits

    Yuriy Natarius,    Hennepin County, IT

    Mirek Chowaniok, Hennepin County, IT



  • Back to Top
    © Copyright 2010, Sybase Inc.