<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sheila&#039;s Blog &#187; build</title>
	<atom:link href="http://sheilapollard.com/tag/build/feed/" rel="self" type="application/rss+xml" />
	<link>http://sheilapollard.com</link>
	<description>Software Development</description>
	<lastBuildDate>Wed, 24 Mar 2010 17:19:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Automating your Build &#8211; The Very Basics for a Beginner</title>
		<link>http://sheilapollard.com/2009/03/24/automating-your-build-the-very-basics-for-a-beginner/?utm_campaign=feed&utm_medium=feed&utm_source=blog</link>
		<comments>http://sheilapollard.com/2009/03/24/automating-your-build-the-very-basics-for-a-beginner/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 12:58:40 +0000</pubDate>
		<dc:creator>Sheila</dc:creator>
				<category><![CDATA[build]]></category>
		<category><![CDATA[ant]]></category>

		<guid isPermaLink="false">http://sheilapollard.wordpress.com/?p=178</guid>
		<description><![CDATA[This post covers the absolute basics for a beginner of setting up a minimal build script for building and deploying code as a jar/war/ear file.]]></description>
			<content:encoded><![CDATA[<p>This post covers the absolute basics for a beginner of setting up a minimal build script for building and deploying code as a jar/war/ear file.  The aim is to show a simple build structure and script rather than building a proper application.  The scripts are mostly self-explanatory.  The end result can be used as a starting point for later posts covering more difficult topics including building sample applications, testing and automating your build with <a href="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2NydWlzZWNvbnRyb2wuc291cmNlZm9yZ2UubmV0">CruiseControl</a>.</p>
<p><em>Prerequisite:</em><br />
You need java and <a href="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2FudC5hcGFjaGUub3JnLw==">ant</a> installed on your machine and running from a command prompt.</p>
<p>The first thing you need when setting up a new project is to decide on the structure.  By using standard conventions about how you structure your code it makes it easier for others to work on it.  You&#8217;ll see a similar type of build structure used in tools like Seam&#8217;s seamgen except more complicated than this one.</p>
<p>The root folder of your project will be referred to as PROJECT_HOME in these notes.  The first thing to do is create the following folders in PROJECT_HOME:<br />
config &#8211; holds configuration files<br />
lib &#8211; holds any jar files<br />
resources &#8211; resource and config files to be copied into a jar, war or ear file during the build<br />
src &#8211; for source java files<br />
web &#8211; for web applications pages, css, images etc</p>
<p>Now add an ant build script file PROJECT_HOME/build.xml which is used to build the project.  Also add PROJECT_HOME/config/build.properties.sample.  This file is added to source control.  Each user that checks out the project will copy this file and rename it to build.properties which will be used by the build script.  Any subsequent changes to the property file in source control will not overwrite a local user&#8217;s settings and this also forces a user to set the properties correctly when checking out a new project.</p>
<p>PROJECT_HOME/config/build.properties.sample:
<code>project.name=example
web.pages.dir=web

javac.debug=true
javac.deprecation=false

jboss.home = C:/Applications/jboss-4.2.2.GA/</code></p>
<p>We start with a basic build script that reads the build.properties file, adds some other properties, a class path and the targets init, compile and clean.  We&#8217;ll add to this as we go along.</p>
<p>The build process generates the folder structure for a jar file, war file and ear file in exploded-archives.  It will then package those into actual archive files in the dist directory.  This allows you to check what&#8217;s being added without having to examine the final archive files.  You also configure a directory to deploy in this case an ear file to a web application server.</p>
<p>PROJECT_HOME/build.xml
<code>&lt;project name="example" default="compile" basedir="."&gt;

  &lt;!-- set properties for this build --&gt;
  &lt;property name="config.dir" value="config" /&gt;
  &lt;property file="${config.dir}/build.properties" /&gt;

  &lt;property name="src.dir" value="src" /&gt;
  &lt;property name="lib.dir" value="lib" /&gt;
  &lt;property name="resources.dir" value="resources" /&gt;
  &lt;property name="dist.dir" value="dist" /&gt;
  &lt;property name="archive.dir" value="exploded-archives" /&gt;
  &lt;property name="ear.dir" value="${archive.dir}/${project.name}.ear" /&gt;
  &lt;property name="jar.dir" value="${archive.dir}/${project.name}.jar" /&gt;
  &lt;property name="war.dir" value="${archive.dir}/${project.name}.war" /&gt;
  &lt;property name="deploy.dir" value="${jboss.home}/server/default/deploy" /&gt;

  &lt;!-- Class path settings --&gt;
  &lt;fileset id="lib" dir="${lib.dir}"&gt;
    &lt;include name="*.jar" /&gt;
  &lt;/fileset&gt;
  &lt;path id="build.classpath"&gt;
    &lt;fileset refid="lib" /&gt;
  &lt;/path&gt;

  &lt;target name="init" description="Initialize the build"&gt;
    &lt;echo&gt;Initialising build...&lt;/echo&gt;
    &lt;mkdir dir="${jar.dir}" /&gt;
    &lt;mkdir dir="${ear.dir}" /&gt;
    &lt;mkdir dir="${war.dir}" /&gt;
    &lt;mkdir dir="${archive.dir}" /&gt;
    &lt;mkdir dir="${dist.dir}" /&gt;
  &lt;/target&gt;

  &lt;target name="compile" depends="init" description="Compile the Java source code"&gt;
    &lt;echo&gt;Compiling java source code...&lt;/echo&gt;
    &lt;javac classpathref="build.classpath" destdir="${jar.dir}" debug="${javac.debug}" deprecation="${javac.deprecation}" nowarn="on"&gt;
      &lt;src path="${src.dir}" /&gt;
    &lt;/javac&gt;
  &lt;/target&gt;

  &lt;target name="clean" description="Cleans up the build directorys"&gt;
    &lt;echo&gt;Cleaning build directories...&lt;/echo&gt;
    &lt;delete dir="${ear.dir}" /&gt;
    &lt;delete dir="${war.dir}" /&gt;
    &lt;delete dir="${jar.dir}" /&gt;
    &lt;delete dir="${archive.dir}" /&gt;
    &lt;delete dir="${dist.dir}" /&gt;
  &lt;/target&gt;

&lt;/project&gt;</code></p>
<p>The build.classpath is set to simply include any jar files in the lib folder.</p>
<p>The init target creates any directories that are needed by the build.</p>
<p>The clean target deletes any directories that were created by the build.</p>
<p>The compile target looks in the src folder for any .java files and compiles them into the exploded-archives/example.jar folder.</p>
<p>To test the build script add the file</p>
<p>PROJECT_HOME/src/com/example/Parent.java
<code>package com.example;

public class Parent {

  private Long parentId;

  public Long getParentId() {
    return this.parentId;
  }

  public void setParentId(Long parentId) {
    this.parentId = parentId;
  }
}</code></p>
<p>Open a command prompt in the PROJECT_HOME folder and run the command &#8216;ant&#8217;.  By default (default=&#8221;compile&#8221;) it will run the compile target.  The compile target states that it depends on the init target, so the init target will be run first to create the folders that are needed.  When the script finishes running you will find that exploded-archives/example.jar/com/example contains the compiled Parent.class.</p>
<p>We want to build and deploy a web application so we add the target gen-war-files which will be used to copy anything that&#8217;s needed into the exploded war file before it gets packaged.  We&#8217;ll start with a target like this:
<code>&lt;?xml version="1.0"?&gt;

  &lt;target name="gen-war-files" depends="compile" description="Generates the war files"&gt;
    &lt;echo&gt;Copying war files...&lt;/echo&gt;
    &lt;copy todir="${war.dir}"&gt;
      &lt;fileset dir="${basedir}/${web.pages.dir}/pages" /&gt;
    &lt;/copy&gt;
    &lt;copy todir="${war.dir}"&gt;
      &lt;fileset dir="${basedir}/${web.pages.dir}"&gt;
        &lt;include name="images/**/*" /&gt;
        &lt;include name="css/**/*" /&gt;
      &lt;/fileset&gt;
    &lt;/copy&gt;
    &lt;copy todir="${war.dir}/WEB-INF/lib"&gt;
      &lt;fileset dir="${lib.dir}"&gt;
        &lt;includesfile name="${config.dir}/war-jars.list" /&gt;
      &lt;/fileset&gt;
    &lt;/copy&gt;
    &lt;copy todir="${war.dir}/WEB-INF"&gt;
      &lt;fileset dir="${resources.dir}/WEB-INF"&gt;
        &lt;include name="*.*"/&gt;
      &lt;/fileset&gt;
    &lt;/copy&gt;
  &lt;/target&gt;</code></p>
<p>A war file contains a WEB-INF folder where compiled classes and required jar files are put.  Also files such as web.xml which gives configuration and deployment for the web components.  So create resources/WEB-INF.</p>
<p>PROJECT_HOME/resources/WEB-INF/web.xml
<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&gt;

&lt;/web-app&gt;</code></p>
<p>The build script copies any files in resources/WEB-INF to the war folder and also copies any jar files that are needed to the WEB-INF/lib folder.  You can configure which of the jar files in PROJECT_HOME/lib get copied over in PROJECT_HOME/config/war-jars.list.  For now just create an empty file of that name in the config folder.</p>
<p>This target copies any files in web/pages to exploded-archives/example.war and will also copy over the images and css folders.  We don&#8217;t have any files to copy at the moment, but will add an index page to see that it does get added.</p>
<p>web/pages/index.jsp
<code>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;The Index Page&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    Index page
  &lt;/body&gt;
&lt;/html&gt;</code></p>
<p>Try the command &#8216;ant gen-war-files&#8217; and you will see that exploded-archives/example.war now contains the index page.</p>
<p>We now add the gen-ear-files and archive targets.  Similarly to the war file, the ear file requires a META-INF folder containing information about the ear file.  So you can add resources/META-INF for holding these files and an empty config/ear-jars.list to configure which jar files are needed in the ear file.  We  will add an application.xml which is the deployment descriptor for ear files.</p>
<p>resources/META-INF/application.xml
<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;application xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/application_5.xsd" 
    version="5"&gt;

    &lt;display-name&gt;example&lt;/display-name&gt;
    &lt;module&gt;
      &lt;ejb&gt;example.jar&lt;/ejb&gt;
    &lt;/module&gt;
    &lt;module&gt;
      &lt;web&gt;
        &lt;web-uri&gt;example.war&lt;/web-uri&gt;
        &lt;context-root&gt;/example&lt;/context-root&gt;
      &lt;/web&gt;
    &lt;/module&gt;
  &lt;/application&gt;</code></p>
<p>The gen-ear-files target will take care of copying this to the correct location in the ear file then the archive target will take all the output in exploded-archives and package up all the files into the dist directory.  Test this using &#8216;ant archive&#8217;
<code>&lt;target name="gen-ear-files" depends="gen-war-files" description="Generates the ear files"&gt;
  &lt;echo&gt;Copying the ear files...&lt;/echo&gt;
  &lt;mkdir dir="${ear.dir}/lib" /&gt;
  &lt;copy todir="${ear.dir}/lib"&gt;
    &lt;fileset dir="${lib.dir}"&gt;
      &lt;includesfile name="${config.dir}/ear-jars.list" /&gt;
    &lt;/fileset&gt;
  &lt;/copy&gt;

  &lt;copy todir="${ear.dir}/META-INF"&gt;
    &lt;fileset dir="${resources.dir}/META-INF"&gt;
      &lt;include name="*.*"/&gt;
    &lt;/fileset&gt;
  &lt;/copy&gt;
&lt;/target&gt;

&lt;target name="archive" depends="gen-war-files,gen-ear-files" description="Packages all the archives"&gt;
  &lt;echo&gt;Packaging all archives...&lt;/echo&gt;
  &lt;jar jarfile="${dist.dir}/${project.name}.jar" basedir="${jar.dir}" /&gt;
  &lt;jar jarfile="${dist.dir}/${project.name}.war" basedir="${war.dir}" /&gt;
  &lt;jar jarfile="${dist.dir}/${project.name}.ear"&gt;
    &lt;fileset dir="${ear.dir}"/&gt;
    &lt;fileset dir="${dist.dir}"&gt;
      &lt;include name="${project.name}.jar"/&gt;
      &lt;include name="${project.name}.war"/&gt;
    &lt;/fileset&gt;
  &lt;/jar&gt;
&lt;/target&gt;</code></p>
<p>We now want to deploy the ear file that has been created to a web application server.  In our example we&#8217;re using JBoss.  You set the jboss.home directory in build.properties already.  Now add some more build targets
<code>&lt;target name="clean-deploy" depends="clean, deploy" description="A full clean deploy"/&gt;

&lt;target name="deploy" depends="archive" description="Deploy to a JBoss web server"&gt;
  &lt;echo&gt;Deploying to JBOSS web server...&lt;/echo&gt;
  &lt;fail unless="jboss.home"&gt;jboss.home not set&lt;/fail&gt;
  &lt;copy todir="${deploy.dir}" file="${dist.dir}/${project.name}.ear" /&gt;
&lt;/target&gt;

&lt;target name="undeploy" description="Undeploy from a JBoss web server"&gt;
  &lt;echo&gt;Undeploying from JBOSS web server...&lt;/echo&gt;
  &lt;delete file="${deploy.dir}/${project.name}.ear" /&gt;
&lt;/target&gt;</code></p>
<p>Now run the clean-deploy target (set this to default) and try accessing http://localhost:8080/example/<br />
You should see the index page display if everything is working correctly.  You now have an extremely basic build script running.  You should go through each line and check that you understand what it does &#8211; you can get more detailed information in the <a href="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2FudC5hcGFjaGUub3JnL21hbnVhbC9pbmRleC5odG1s">Ant User Manual</a>.</p>
<br /><a href="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3NoZWlsYXBvbGxhcmQud29yZHByZXNzLmNvbS8/cD0xNzgjY29tbWVudHM=" title=\"Comments on &quot;Automating your Build &#8211; The Very Basics for a Beginner&quot;\"><img src="http://sheilapollard.com/wp-content/plugins/feed-comments-number/image.php?178" alt="Comments" /></a> <img src="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?view=1&post_id=178" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://sheilapollard.com/2009/03/24/automating-your-build-the-very-basics-for-a-beginner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
