In this tutorial, we will show you how to use Ant build script to create a Jar file and working with the project’s external libraries / dependencies.

Technologies used :

  1. Eclipse 4.2
  2. JDK 1.7
  3. Ant 1.9.4
  4. Ant-Ivy 2.4
  5. logback 1.1.2
  6. joda-time 2.5

P.S Previous Ant Java project will be reused.

1. Project Structure

Figure 1.1 : The final project directory structure, in Eclipse IDE.

ant-external-libraries-final

2. Java Project + External Libraries

In Eclipse IDE, reopen the previous Java project AntDateUtils, update the source code to use logback and joda-time.

src/com/mkyong/core/utils/DateUtils.java

package com.mkyong.core.utils;

import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DateUtils {

	private static final Logger logger = LoggerFactory.getLogger(DateUtils.class);
	
	public static void main(String[] args) {

		logger.debug("[MAIN] Current Date : {}", getLocalCurrentDate());
		System.out.println(getLocalCurrentDate());
		
	}

	private static String getLocalCurrentDate() {
	
		LocalDate date = new LocalDate();
		return date.toString();
		
	}

}

Create a logback.xml and put it in the project src folder. Refer to figure 1.1

src/logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
	  <layout class="ch.qos.logback.classic.PatternLayout">
 
		<Pattern>
			ANT + LogBack : %-5level %logger{36} - %msg%n
		</Pattern>
 
	  </layout>
	</appender>
 
	<root level="debug">
	  <appender-ref ref="STDOUT" />
	</root>
 
</configuration>

3. Ivy – Get External Libraries

We use Apache Ivy to get the project’s external libraries / dependencies.

3.1 Create this file ivy.xml :

ivy.xml

<ivy-module version="2.0">
	<info organisation="org.apache" module="dateUtilsProject" />
	<dependencies>
		<dependency org="joda-time" name="joda-time" rev="2.5"  />
		<dependency org="org.slf4j" name="slf4j-api" rev="1.7.6" />
		<dependency org="ch.qos.logback" name="logback-classic" rev="1.1.2" />
	</dependencies>
</ivy-module>

3.2 Update build.xml, add ivy namespace on top, and “ivy” task to download the ivy module, and “resolve” task to ask Ivy module to download the external libraries.

build.xml

<project xmlns:ivy="antlib:org.apache.ivy.ant" 
	name="dateUtilsProject" default="main" basedir=".">

	<!-- ivy start -->
	<!-- ivy to get dependencies and copy to project lib folder automatically -->
	<target name="resolve" description="retrieve dependencies with ivy">
		<ivy:retrieve />
	</target>

	<!-- install ivy -->
	<target name="ivy" description="Install ivy">
		<mkdir dir="${user.home}/.ant/lib" />
		<get dest="${user.home}/.ant/lib/ivy.jar" 
			src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.4.0-rc1/ivy-2.4.0-rc1.jar" />
	</target>
	<!-- ivy end -->

</project>

For the first time, download the ivy module from Maven center repository to local ${user.home}/.ant/lib/ivy.jar.


$ ant ivy

To download the external libraries, run task “resolve”. The declared libraries will be downloaded to the project lib folder.


$ ant resolve

4. build.xml

Review the updated build.xml script, read comments for self-explanatory.

Main points :

  1. Manage the project external libraries with Apache Ivy, review the ivy namespace on top, and task “resolve”.
  2. To compile the source code, you need to declares the classpath. Review task “compile”, and “classpathref” attribute.
  3. In “jar” task, constructs the entire list of the external libraries and put it into the manifest.mf file.
  4. In “jar” task, the project jar will be packaged to folder “dist” and the entire external libraries will be copied to from “lib” to “dist/lib”.
build.xml

<project xmlns:ivy="antlib:org.apache.ivy.ant" 
       name="dateUtilsProject" default="main" basedir=".">
	<description>
		Create a Java Project (JAR) with Ant build script
	</description>

	<property name="projectName" value="DateUtils" />
	<property name="src.dir" location="src" />
	<property name="build.dir" location="bin" />
	<property name="dist.dir" location="dist" />
	<property name="dist.lib.dir" location="dist/lib" />
	<property name="lib.dir" value="lib" />
	<property name="main-class" value="com.mkyong.core.utils.DateUtils" />

	<!-- ivy start -->
	<!-- ivy to get dependencies and copy to project lib folder automatically -->
	<target name="resolve" description="retrieve dependencies with ivy">
		<ivy:retrieve />
	</target>

	<!-- install ivy -->
	<target name="ivy" description="Install ivy">
		<mkdir dir="${user.home}/.ant/lib" />
		<get dest="${user.home}/.ant/lib/ivy.jar" src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.4.0-rc1/ivy-2.4.0-rc1.jar" />
	</target>
	<!-- ivy end -->

	<target name="init">
		<mkdir dir="${build.dir}" />
	</target>

	<!-- external libraries classpath, we don't need sources and javadoc -->
	<path id="classpath">
		<fileset dir="${basedir}/">
			<include name="${lib.dir}/*.jar" />
			<exclude name="${lib.dir}/*sources.jar"/>
			<exclude name="${lib.dir}/*javadoc.jar"/>
		</fileset>
	</path>

	<!-- To work with external libraries, need classpath to compile -->
	<target name="compile" depends="init" description="compile the source ">
		<javac includeantruntime="false" srcdir="${src.dir}" destdir="${build.dir}" classpathref="classpath" />
	</target>

	<!-- constructs the external libraries classpath name -->
	<pathconvert property="classpath.name" pathsep=" ">
		<path refid="classpath" />
		<mapper>
			<chainedmapper>
				<flattenmapper />
				<globmapper from="*.jar" to="lib/*.jar" />
			</chainedmapper>
		</mapper>
	</pathconvert>

	<target name="copy-dependencies">
		<copy todir="${dist.lib.dir}">
			<fileset dir="${lib.dir}" includes="**/*.jar" excludes="**/*sources.jar, **/*javadoc.jar" />
		</copy>
	</target>

	<!-- jar it, and declares the ext libraries in manifest.mf file -->
	<target name="jar" depends="compile, copy-dependencies" description="package, output to JAR">

		<echo message="classpath.name : ${classpath.name} " />

		<mkdir dir="${dist.dir}" />
		<mkdir dir="${dist.lib.dir}" />

		<jar jarfile="${dist.dir}/${projectName}.jar" basedir="${build.dir}">
			<manifest>
				<attribute name="Main-Class" value="${main-class}" />
				<attribute name="Class-Path" value="${classpath.name}" />
			</manifest>
		</jar>
	</target>

	<target name="clean" description="clean up">
		<delete dir="${build.dir}" />
		<delete dir="${dist.dir}" />
	</target>

	<!-- Default, run this -->
	<target name="main" depends="clean, compile, jar" />

</project>

5. Test

Test the Java project with Ant build script.

5.1 Jar it.


$ pwd
/Users/mkyong/Documents/workspace/AntDateUtils

$ ant
Buildfile: /Users/mkyong/Documents/workspace/AntDateUtils/build.xml

clean:
   [delete] Deleting directory /Users/mkyong/Documents/workspace/AntDateUtils/bin
   [delete] Deleting directory /Users/mkyong/Documents/workspace/AntDateUtils/dist

init:
    [mkdir] Created dir: /Users/mkyong/Documents/workspace/AntDateUtils/bin

compile:
    [javac] Compiling 1 source file to /Users/mkyong/Documents/workspace/AntDateUtils/bin

copy-dependencies:
     [copy] Copying 12 files to /Users/mkyong/Documents/workspace/AntDateUtils/dist/lib

jar:
     [echo] classpath.name : ... lib/joda-time-2.5.jar lib/logback-classic-1.1.2.jar lib/logback-core-1.1.2.jar lib/mail-1.4.jar ...

      [jar] Building jar: /Users/mkyong/Documents/workspace/AntDateUtils/dist/DateUtils.jar

main:

BUILD SUCCESSFUL
Total time: 1 second

5.2 Inspects the generated jar file.


$ jar -tf dist/DateUtils.jar 

META-INF/
META-INF/MANIFEST.MF
com/
com/mkyong/
com/mkyong/core/
com/mkyong/core/utils/
com/mkyong/core/utils/DateUtils.class
META-INF/MANIFEST.MF

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.4
Created-By: 1.7.0_05-b05 (Oracle Corporation)
Main-Class: com.mkyong.core.utils.DateUtils
Class-Path: lib/activation-1.1.jar lib/commons-compiler-2.6.1.jar lib/
 geronimo-jms_1.1_spec-1.0.jar lib/groovy-all-2.0.7.jar lib/janino-2.6
 .1.jar lib/joda-convert-1.2.jar lib/joda-time-2.5.jar lib/logback-cla
 ssic-1.1.2.jar lib/logback-core-1.1.2.jar lib/mail-1.4.jar lib/servle
 t-api-2.5.jar lib/slf4j-api-1.7.6.jar

5.3 Run the Jar file.


$ pwd
/Users/mkyong/Documents/workspace/AntDateUtils

$ java -jar dist/DateUtils.jar 

16:28:43.957 [main] DEBUG com.mkyong.core.utils.DateUtils - [MAIN] Current Date : 2014-11-21
2014-11-21

5.4 Run the Jar file again, with logback.xml.


$ pwd
/Users/mkyong/Documents/workspace/AntDateUtils

$ java -jar -Dlogback.configurationFile=src/logback.xml dist/DateUtils.jar

16:34:43,746 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [src/logback.xml] at [file:/Users/mkyong/Documents/workspace/AntDateUtils/src/logback.xml]
//...

ANT + LogBack : DEBUG com.mkyong.core.utils.DateUtils - [MAIN] Current Date : 2014-11-21
2014-11-21

Download Source Code

Download it – AntDateUtils-External-Libraries.zip (8 KB)

References

  1. Apache Ant Hello World Official Guide
  2. How To Create A Jar File With Maven
  3. Ant Jar task
  4. Ant Copy task