Tuesday, April 30, 2013

How to create EAR file using ANT(Build Management Tool)?

In this post we will see how to create EAR(Enterprise ARchive ) using Apache ANT. And we will also see how this build.xml flow is created !!

What is an Enterprise Application ?
An Enterprise Application is a assembling of various resources(WAR,JAR,RAR) into one deployable unit. And that’s finally packaged as .ear file.

What is Enterprise Application ?

Implementation part ?
1] Consider the following scenario, in your project Arithmetic you have developed three different type of Applications
  • simpleArithmeticV1 –> we need to bundle this as a separate WAR file
  • simpleArithmeticV2 –> we need to bundle this as a separate WAR file
  • simpleArithmeticV3 –> we need to bundle this as a separate WAR file
2] Once this WAR files generation completed for all the 3 modules, finally we need put it  all together and generate EAR file.Refer this following diagram for reference.

EAR file generation

What is the general flow of various targets involved in build.xml ?
Here we have created a Single build.xml file which would perform WAR file generation for multiple projects.And finally generate a consolidated EAR file.

single build file for multiple projects

Steps Involved:
1. At the execution of this build.xml the default target specified is get called first.
<project name="ExplodedEar" default="App1,App2,App3" basedir=".">
Now controlled is transfer to the target named App1,App2,App3(case sensitive).
2. Target App1,App2,App3 depends on it’s respective initialization target namely initApp1,initApp2 and initApp3.
<target name="initApp1" description="Variable Initialization">
  <!-- Define the properties used by the build -->
  <echo> Defining properties for initApp1 </echo>
  <property name="app.name"       value="simpleArithmeticV1(purple)"/>
  <property name="work.home"       value="${basedir}/${app.name}/work"/>
  <property name="dist.home"       value="${basedir}/${app.name}/dist"/>
  <property name="src.home"        value="${basedir}/${app.name}/src"/>
  <property name="web.home"        value="${basedir}/${app.name}/WebContent"/>
  </target>
  <target name="initApp2" description="Variable Initialization">
  <!-- Define the properties used by the build -->
  <echo> Defining properties for initApp2 </echo>
  <var name="app.name" unset="true"/>
  <var name="work.home" unset="true"/>
  <var name="dist.home" unset="true"/>
  <var name="src.home" unset="true"/>
  <var name="web.home" unset="true"/>
  <property name="app.name"       value="simpleArithmeticV2(navy)"/>
  <property name="work.home"       value="${basedir}/${app.name}/work"/>
  <property name="dist.home"       value="${basedir}/${app.name}/dist"/>
  <property name="src.home"        value="${basedir}/${app.name}/src"/>
  <property name="web.home"        value="${basedir}/${app.name}/WebContent"/>
   </target>
  <target name="initApp3" description="Variable Initialization">
  <!-- Define the properties used by the build -->
  <echo> Defining properties for initApp3 </echo>
  <var name="app.name" unset="true"/>
  <var name="work.home" unset="true"/>
  <var name="dist.home" unset="true"/>
  <var name="src.home" unset="true"/>
  <var name="web.home" unset="true"/> 
  <property name="app.name"       value="simpleArithmeticV3(green)"/>
  <property name="work.home"       value="${basedir}/${app.name}/work"/>
  <property name="dist.home"       value="${basedir}/${app.name}/dist"/>
  <property name="src.home"        value="${basedir}/${app.name}/src"/>
  <property name="web.home"        value="${basedir}/${app.name}/WebContent"/>
  </target>
3. Target initApp1,initApp2,initApp3 depends on generalized targets clean,prepare,compile,dist.
clean Target:
<target name="clean"  description="Delete old work and dist directories">
    <delete dir="${work.home}"/>
    <delete dir="${dist.home}"/>
 <delete file="${war.home}/${ear.name}"/>
  </target>
prepare Target:
  <target name="prepare"  description="Create working dirs and copy static files to work dir">
    <mkdir  dir="${dist.home}"/>
    <mkdir  dir="${work.home}/WEB-INF/classes"/>
    <!-- Copy static HTML and JSP files to work dir -->
    <copy todir="${work.home}">
      <fileset dir="${web.home}"/>
    </copy>
  </target>
compile Target:
  <target name="compile" 
          description="Compile Java sources and copy to WEB-INF/classes dir">
    <javac srcdir="${src.home}" destdir="${work.home}/WEB-INF/classes" debug="true" debuglevel="lines,vars,source">
 <classpath refid="compile.classpath"/>
    </javac> 
  <copy  todir="${work.home}/WEB-INF/classes">
      <fileset dir="${src.home}" excludes="**/*.java"/>
    </copy>
  </target>
dist Target:
<target name="dist" 
          description="Create WAR file for binary distribution">
    <war destfile="${dist.home}/${app.name}.war">
   <fileset dir="${work.home}"/>
   <classes dir="${work.home}/WEB-INF/classes"/>
    </war>
  <copy file="${dist.home}/${app.name}.war" todir="${war.home}" overwrite="true" />
  </target>
ear Target:
<target name="ear" >
  <ear destfile="${war.home}/${ear.name}" appxml="${app.home}" update="true">
      <fileset dir="${jar.home}" includes="*.jar"/>
      <fileset dir="${war.home}" includes="*.war"/>
    </ear>
 </target>
Complete Build.xml used to create EAR:
<?xml version="1.0" encoding="UTF-8"?>

<project name="ExplodedEar" default="App1,App2,App3" basedir=".">  
    <!-- Define the properties used by the build -->
  <property name="war.home"       value="${basedir}/war"/>
  <property name="jar.home"       value="${basedir}/lib"/>
  <property name="app.home"        value="${basedir}/application.xml"/>
  <property name="ear.name"     value="myapp.ear"/>
  <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
  <target name="App1" depends="initApp1,clean,prepare,compile,dist" description="Clean work dirs, then compile and create a WAR">
  <echo> Building completed for initApp1 </echo>
  </target>
  <target name="App2" depends="initApp2,clean,prepare,compile,dist" description="Clean work dirs, then compile and create a WAR">
  <echo> Building completed for initApp2 </echo>
  </target>
  <target name="App3" depends="initApp3,clean,prepare,compile,dist,ear" description="Clean work dirs, then compile and create a WAR">
  <echo> Building completed for initApp3 </echo>
  </target>
  <target name="initApp1" description="Variable Initialization">
    <!-- Define the properties used by the build -->
 
  <echo> Defining properties for initApp1 </echo>
  <property name="app.name"       value="simpleArithmeticV1(purple)"/>
  <property name="work.home"       value="${basedir}/${app.name}/work"/>
  <property name="dist.home"       value="${basedir}/${app.name}/dist"/>
  <property name="src.home"        value="${basedir}/${app.name}/src"/>
  <property name="web.home"        value="${basedir}/${app.name}/WebContent"/>
  </target>
  
  <target name="initApp2" description="Variable Initialization">
    <!-- Define the properties used by the build -->
 
 <echo> Defining properties for initApp2 </echo>
 <var name="app.name" unset="true"/>
 <var name="work.home" unset="true"/>
 <var name="dist.home" unset="true"/>
 <var name="src.home" unset="true"/>
 <var name="web.home" unset="true"/>
 
  <property name="app.name"       value="simpleArithmeticV2(navy)"/>
  <property name="work.home"       value="${basedir}/${app.name}/work"/>
  <property name="dist.home"       value="${basedir}/${app.name}/dist"/>
  <property name="src.home"        value="${basedir}/${app.name}/src"/>
  <property name="web.home"        value="${basedir}/${app.name}/WebContent"/>
   </target>
  
  <target name="initApp3" description="Variable Initialization">
    <!-- Define the properties used by the build -->
 
 <echo> Defining properties for initApp3 </echo>
 <var name="app.name" unset="true"/>
 <var name="work.home" unset="true"/>
 <var name="dist.home" unset="true"/>
 <var name="src.home" unset="true"/>
 <var name="web.home" unset="true"/>
 
  <property name="app.name"       value="simpleArithmeticV3(green)"/>
  <property name="work.home"       value="${basedir}/${app.name}/work"/>
  <property name="dist.home"       value="${basedir}/${app.name}/dist"/>
  <property name="src.home"        value="${basedir}/${app.name}/src"/>
  <property name="web.home"        value="${basedir}/${app.name}/WebContent"/>
  </target>
  
  <!-- Define the CLASSPATH -->
  <path id="compile.classpath"> 
  
  </path>
  
  <target name="clean"  description="Delete old work and dist directories">
    <delete dir="${work.home}"/>
    <delete dir="${dist.home}"/>
 <delete file="${war.home}/${ear.name}"/>
  </target>
  
  <target name="prepare"  description="Create working dirs and copy static files to work dir">
    <mkdir  dir="${dist.home}"/>
    <mkdir  dir="${work.home}/WEB-INF/classes"/>
    <!-- Copy static HTML and JSP files to work dir -->
    <copy todir="${work.home}">
      <fileset dir="${web.home}"/>
    </copy>
  </target>
  
  <target name="compile" 
          description="Compile Java sources and copy to WEB-INF/classes dir">
    <javac srcdir="${src.home}" destdir="${work.home}/WEB-INF/classes" debug="true" debuglevel="lines,vars,source">
 <classpath refid="compile.classpath"/>
    </javac> 
  <copy  todir="${work.home}/WEB-INF/classes">
      <fileset dir="${src.home}" excludes="**/*.java"/>
    </copy>
  </target>
  
  <target name="dist" 
          description="Create WAR file for binary distribution">
    <war destfile="${dist.home}/${app.name}.war">
   <fileset dir="${work.home}"/>
   <classes dir="${work.home}/WEB-INF/classes"/>
    </war>
  <copy file="${dist.home}/${app.name}.war" todir="${war.home}" overwrite="true" />
  </target>
 
  <target name="ear" >
  <ear destfile="${war.home}/${ear.name}" appxml="${app.home}" update="true">
      <fileset dir="${jar.home}" includes="*.jar"/>
      <fileset dir="${war.home}" includes="*.war"/>
    </ear>
 </target>
 
</project> 

That’s it , we have created a Archived EAR file using build.xml , now just deploy this bundled EAR to some Application Servers like Oracle Weblogic, Redhat JBoss, IBM WebSphere,Oracle Glassfish.In the future posts we will discuss about how to deploy the application straight away to application server using ANT  tasks.

2 comments:

  1. Thanks for this post.. this is so useful... I have a question...
    Once I was asked a question..
    Project A - depends on Project B
    Project B - depends on Project C
    Project C - depends on Project A
    so how we're going to build these projects(resolving the dependencies)???? - Could you please help...

    ReplyDelete
  2. Hi Ariv,

    for the below scenario,

    A --depends----> B -----depends----> C --depends---->A

    since in most of the cases not the entire project will not be dependent, just some part of it will be, so separate out the dependent part,
    say for the above scenario CA.
    Now,
    A --depends--->B --depends--> C , CA---depends--->A
    now C doesn't depend on A hence this circular dependency will be avoided.

    ReplyDelete