{"id":112,"date":"2026-10-12T07:52:16","date_gmt":"2026-10-12T07:52:16","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2009\/01\/28\/apache-ant-learn-apache-ant-from-ibm-experts\/"},"modified":"2026-10-12T07:52:16","modified_gmt":"2026-10-12T07:52:16","slug":"apache-ant-learn-apache-ant-from-ibm-experts","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/apache-ant-learn-apache-ant-from-ibm-experts\/","title":{"rendered":"Apache Ant for DevOps Engineers: Build Files, Dependencies, and Custom Tasks"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Originally published on 2009-01-28; fully revised and updated.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><img src='https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2009\/01\/learn-apache-ant.png' alt='learn-apache-ant-from-experts' \/><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Apache Ant is a Java-based build automation tool that defines repeatable build steps in XML. This guide is for engineers maintaining Java build pipelines who want a clear refresher on Ant fundamentals: build file anatomy, dependency-driven execution, command-line usage, packaging, filesystem operations, and custom task extension.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Apache Ant at a glance<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ant is most useful when you need explicit control over build steps and cross-platform behavior without relying on shell-specific scripts. The original tutorial compared Ant to make; in modern teams, Ant is also often evaluated alongside Maven and Gradle.<\/p>\n\n\n\n<figure class='wp-block-table'><table class='has-fixed-layout'><thead><tr><th>Tool<\/th><th>Configuration style<\/th><th>Typical strength<\/th><th>Common trade-off<\/th><\/tr><\/thead><tbody><tr><td>Ant<\/td><td>Explicit XML tasks and targets<\/td><td>Fine-grained control of build steps<\/td><td>Verbose configuration for large projects<\/td><\/tr><tr><td>Make<\/td><td>Rules plus shell commands<\/td><td>Simple and language-agnostic<\/td><td>Portability issues across shells and platforms<\/td><\/tr><tr><td>Maven<\/td><td>Convention-driven lifecycle and plugins<\/td><td>Standardized Java project structure<\/td><td>Less explicit control over each step<\/td><\/tr><tr><td>Gradle<\/td><td>Programmable DSL (Groovy or Kotlin)<\/td><td>Flexible build logic and ecosystem integration<\/td><td>Higher complexity for teams new to DSL-based builds<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Anatomy of a minimal build.xml<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">An Ant build file has one top-level <strong>project<\/strong>, with one or more <strong>target<\/strong> elements. Targets contain <strong>tasks<\/strong> (such as <code>javac<\/code>, <code>jar<\/code>, <code>copy<\/code>, <code>delete<\/code>) that perform the actual work.<\/p>\n\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\" class='language-xml'><span class=\"hljs-meta\">&lt;?xml version='1.0'?&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">project<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'demo'<\/span> <span class=\"hljs-attr\">default<\/span>=<span class=\"hljs-string\">'hello'<\/span> <span class=\"hljs-attr\">basedir<\/span>=<span class=\"hljs-string\">'.'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'hello'<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">echo<\/span> <span class=\"hljs-attr\">message<\/span>=<span class=\"hljs-string\">'Hello from Ant'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">project<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Properties are immutable once set, and are typically used for paths and reusable values.<\/p>\n\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\" class='language-xml'><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">property<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'src.dir'<\/span> <span class=\"hljs-attr\">location<\/span>=<span class=\"hljs-string\">'src'<\/span>\/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">property<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'build.dir'<\/span> <span class=\"hljs-attr\">location<\/span>=<span class=\"hljs-string\">'build'<\/span>\/&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'compile'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">javac<\/span> <span class=\"hljs-attr\">srcdir<\/span>=<span class=\"hljs-string\">'${src.dir}'<\/span> <span class=\"hljs-attr\">destdir<\/span>=<span class=\"hljs-string\">'${build.dir}'<\/span> <span class=\"hljs-attr\">debug<\/span>=<span class=\"hljs-string\">'true'<\/span>\/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Dependency-driven build flow<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ant runs targets based on dependencies, not file order. If <code>dist<\/code> depends on <code>compile<\/code>, and <code>compile<\/code> depends on <code>init<\/code>, Ant resolves that chain automatically.<\/p>\n\n\n\n<pre class='mermaid'>\nflowchart TD\n    A[Run ant dist] --&gt; B[Resolve dependencies]\n    B --&gt; C[init target]\n    C --&gt; D[compile target]\n    D --&gt; E[dist target]\n    E --&gt; F[Jar artifact in dist directory]\n<\/pre>\n\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\" class='language-xml'><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'init'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">mkdir<\/span> <span class=\"hljs-attr\">dir<\/span>=<span class=\"hljs-string\">'build'<\/span>\/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'compile'<\/span> <span class=\"hljs-attr\">depends<\/span>=<span class=\"hljs-string\">'init'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">javac<\/span> <span class=\"hljs-attr\">srcdir<\/span>=<span class=\"hljs-string\">'src'<\/span> <span class=\"hljs-attr\">destdir<\/span>=<span class=\"hljs-string\">'build'<\/span>\/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'dist'<\/span> <span class=\"hljs-attr\">depends<\/span>=<span class=\"hljs-string\">'compile'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">jar<\/span> <span class=\"hljs-attr\">destfile<\/span>=<span class=\"hljs-string\">'dist\/app.jar'<\/span> <span class=\"hljs-attr\">basedir<\/span>=<span class=\"hljs-string\">'build'<\/span>\/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Running Ant from the command line<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The default command is simply <code>ant<\/code>, which executes the build file&#8217;s default target. You can then override file names, set properties, or call specific targets.<\/p>\n\n\n\n<figure class='wp-block-table'><table class='has-fixed-layout'><thead><tr><th>Command or option<\/th><th>What it does<\/th><th>Example<\/th><\/tr><\/thead><tbody><tr><td>ant<\/td><td>Runs default target in build.xml<\/td><td>ant<\/td><\/tr><tr><td>-f or -buildfile<\/td><td>Uses a non-default build file name<\/td><td>ant -f build-prod.xml dist<\/td><\/tr><tr><td>-Dname=value<\/td><td>Sets a property before parsing build.xml<\/td><td>ant -Denv=staging clean dist<\/td><\/tr><tr><td>-p<\/td><td>Prints available targets<\/td><td>ant -p<\/td><\/tr><tr><td>target names<\/td><td>Runs one or more explicit targets<\/td><td>ant clean compile dist<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<pre class='wp-block-code'><span><code class=\"hljs\" class='language-bash'>ant\nant -f build.xml clean dist\nant -Dmetal=beryllium compile\nant -p<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The original material also showed Eclipse integration (Ant editor, target execution, and console output). Those concepts remain useful, though exact UI steps vary by Eclipse version.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Complete example: compile, package, and timestamp a Java build<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This example mirrors the classic Ant workflow: initialize directories, compile Java sources, and create a date-stamped JAR.<\/p>\n\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\" class='language-xml'><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">project<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'java-example'<\/span> <span class=\"hljs-attr\">default<\/span>=<span class=\"hljs-string\">'dist'<\/span> <span class=\"hljs-attr\">basedir<\/span>=<span class=\"hljs-string\">'.'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">description<\/span>&gt;<\/span>Simple Java project build<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">description<\/span>&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">property<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'src.dir'<\/span> <span class=\"hljs-attr\">location<\/span>=<span class=\"hljs-string\">'src'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">property<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'build.dir'<\/span> <span class=\"hljs-attr\">location<\/span>=<span class=\"hljs-string\">'build'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">property<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'dist.dir'<\/span> <span class=\"hljs-attr\">location<\/span>=<span class=\"hljs-string\">'dist'<\/span>\/&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'clean'<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">delete<\/span> <span class=\"hljs-attr\">dir<\/span>=<span class=\"hljs-string\">'${build.dir}'<\/span>\/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">delete<\/span> <span class=\"hljs-attr\">dir<\/span>=<span class=\"hljs-string\">'${dist.dir}'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'init'<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tstamp<\/span>\/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">mkdir<\/span> <span class=\"hljs-attr\">dir<\/span>=<span class=\"hljs-string\">'${build.dir}'<\/span>\/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">mkdir<\/span> <span class=\"hljs-attr\">dir<\/span>=<span class=\"hljs-string\">'${dist.dir}'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'compile'<\/span> <span class=\"hljs-attr\">depends<\/span>=<span class=\"hljs-string\">'init'<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">javac<\/span> <span class=\"hljs-attr\">srcdir<\/span>=<span class=\"hljs-string\">'${src.dir}'<\/span> <span class=\"hljs-attr\">destdir<\/span>=<span class=\"hljs-string\">'${build.dir}'<\/span> <span class=\"hljs-attr\">debug<\/span>=<span class=\"hljs-string\">'true'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'dist'<\/span> <span class=\"hljs-attr\">depends<\/span>=<span class=\"hljs-string\">'compile'<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">jar<\/span> <span class=\"hljs-attr\">destfile<\/span>=<span class=\"hljs-string\">'${dist.dir}\/package-${DSTAMP}.jar'<\/span> <span class=\"hljs-attr\">basedir<\/span>=<span class=\"hljs-string\">'${build.dir}'<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">manifest<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">attribute<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'Main-Class'<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">'com.example.Main'<\/span>\/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">manifest<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">jar<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">project<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class='wp-block-code'><span><code class=\"hljs\" class='language-bash'>ant clean dist\njava -jar dist\/package-*.jar<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Filesystem tasks, patterns, and selectors<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ant includes strong cross-platform filesystem primitives. Common tasks include <code>mkdir<\/code>, <code>delete<\/code>, <code>copy<\/code>, <code>move<\/code>, <code>zip<\/code>, <code>jar<\/code>, and <code>replace<\/code>. Pattern-based filesets and selectors let you work on groups of files safely and repeatably.<\/p>\n\n\n\n<ul class='wp-block-list'><li>Use <strong>fileset include\/exclude<\/strong> for wildcard matching such as <code>**\/*.java<\/code>.<\/li><li>Use <strong>selectors<\/strong> (size, date, contains, and logical containers) for precise file filtering.<\/li><li>Keep path handling portable by favoring Ant path handling and relative locations.<\/li><\/ul>\n\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\" class='language-xml'><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">copy<\/span> <span class=\"hljs-attr\">todir<\/span>=<span class=\"hljs-string\">'${build.dir}\/resources'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">fileset<\/span> <span class=\"hljs-attr\">dir<\/span>=<span class=\"hljs-string\">'src'<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">include<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'**\/*.properties'<\/span>\/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">exclude<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'**\/*test*'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">fileset<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">copy<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">replace<\/span> <span class=\"hljs-attr\">file<\/span>=<span class=\"hljs-string\">'config\/app.properties'<\/span> <span class=\"hljs-attr\">token<\/span>=<span class=\"hljs-string\">'@BUILD_DATE@'<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">'${DSTAMP}'<\/span>\/&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\" class='language-xml'><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">fileset<\/span> <span class=\"hljs-attr\">dir<\/span>=<span class=\"hljs-string\">'src'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">include<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'**\/*.txt'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">and<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">size<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">'512'<\/span> <span class=\"hljs-attr\">when<\/span>=<span class=\"hljs-string\">'more'<\/span>\/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">contains<\/span> <span class=\"hljs-attr\">text<\/span>=<span class=\"hljs-string\">'hello'<\/span> <span class=\"hljs-attr\">casesensitive<\/span>=<span class=\"hljs-string\">'no'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">and<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">fileset<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Extending Ant with a custom task<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ant can be extended by writing Java classes that extend <code>org.apache.tools.ant.Task<\/code> and implement <code>execute()<\/code>. This is useful when shelling out with <code>exec<\/code> would make builds less portable or harder to maintain.<\/p>\n\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\" class='language-java'><span class=\"hljs-keyword\">import<\/span> java.io.File;\n<span class=\"hljs-keyword\">import<\/span> org.apache.tools.ant.BuildException;\n<span class=\"hljs-keyword\">import<\/span> org.apache.tools.ant.Task;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">FileSorter<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Task<\/span> <\/span>{\n    private File file;\n    private File tofile;\n\n    public <span class=\"hljs-keyword\">void<\/span> setFile(File file) { <span class=\"hljs-keyword\">this<\/span>.file = file; }\n    public <span class=\"hljs-keyword\">void<\/span> setTofile(File tofile) { <span class=\"hljs-keyword\">this<\/span>.tofile = tofile; }\n\n    @Override\n    public <span class=\"hljs-keyword\">void<\/span> execute() throws BuildException {\n        <span class=\"hljs-comment\">\/\/ read file, sort lines, write to tofile<\/span>\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\" class='language-xml'><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">project<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'custom-task-demo'<\/span> <span class=\"hljs-attr\">default<\/span>=<span class=\"hljs-string\">'main'<\/span> <span class=\"hljs-attr\">basedir<\/span>=<span class=\"hljs-string\">'.'<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">taskdef<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'filesorter'<\/span> <span class=\"hljs-attr\">classname<\/span>=<span class=\"hljs-string\">'FileSorter'<\/span> <span class=\"hljs-attr\">classpath<\/span>=<span class=\"hljs-string\">'.'<\/span>\/&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">'main'<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">filesorter<\/span> <span class=\"hljs-attr\">file<\/span>=<span class=\"hljs-string\">'input.txt'<\/span> <span class=\"hljs-attr\">tofile<\/span>=<span class=\"hljs-string\">'output.txt'<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">project<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class='wp-block-code' aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\" class='language-bash'>javac -cp $ANT_HOME\/lib\/ant.jar FileSorter.java\nant -f build-custom.xml main<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Resources and attribution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This topic was originally presented as an IBM developerWorks tutorial by Matt Chapman, and this revised version keeps the core concepts while modernizing structure and examples.<\/p>\n\n\n\n<ul class='wp-block-list'><li><a href='http:\/\/ant.apache.org\/'>Apache Ant home page<\/a><\/li><li><a href='http:\/\/ant.apache.org\/external.html#IDE%20and%20Editor%20Integration'>Ant IDE and editor integration<\/a><\/li><li><a href='http:\/\/www.eclipse.org\/'>Eclipse<\/a><\/li><li><a href='http:\/\/www.cygwin.com\/'>Cygwin<\/a><\/li><li><a href='http:\/\/www.cvshome.org'>CVS<\/a><\/li><li>Original reference link from the legacy post: <a href='http:\/\/www.ibm.com\/developerworks\/edu\/j-dw-java-apant-i.html'>http:\/\/www.ibm.com\/developerworks\/edu\/j-dw-java-apant-i.html<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices and common pitfalls<\/h2>\n\n\n\n<ul class='wp-block-list'><li>Split large builds into logical targets and use <code>depends<\/code> for order, not file position.<\/li><li>Use properties for directories and artifact names; avoid hard-coded absolute paths.<\/li><li>Keep a <code>clean<\/code> target to remove generated output and support reproducible rebuilds.<\/li><li>Prefer filesets and selectors over ad hoc file loops for clarity and portability.<\/li><li>Use custom tasks when behavior is reused across builds; otherwise keep logic in standard tasks.<\/li><li>Treat older Ant, CVS, and IDE-specific guidance as historical context and validate against your current toolchain.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A practical, modernized guide to Apache Ant fundamentals for Java build automation. Learn build.xml structure, dependency flow, command-line execution, packaging, and safe extension with custom tasks.<\/p>\n","protected":false},"author":1,"featured_media":3994,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[8],"tags":[209,3005,1836,2997,1897,3006,3002,1837,1835,3001,3000,3003,2998,3004,100,97,2999,1682,1748,1673,3007,105,1749,98],"class_list":["post-112","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-training","tag-ant","tag-ant-coach","tag-ant-course","tag-ant-expert","tag-ant-guide","tag-ant-instructor","tag-ant-professional","tag-ant-trainer","tag-ant-training","tag-ant-training-by-expert-trainers","tag-ant-training-by-experts","tag-ant-training-by-professionals","tag-ant-tutorial","tag-apache-ant-ibm-expert","tag-hyderabad","tag-india","tag-learn-ant","tag-mumbai","tag-netherlands","tag-pune","tag-singapore","tag-trainer","tag-uk","tag-usa"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/112","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=112"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/112\/revisions"}],"predecessor-version":[{"id":78956,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/112\/revisions\/78956"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/3994"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=112"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=112"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=112"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}