April 9th, 2013 by Jean-Louis Boudart
In a previous article you have seen EasyAnt basics. This does the job most of the time but who has never needed custom logic in their projects ? This usually happens when you have project specific constraints or because a feature doesn’t exist yet in your favorite build tool.
Fortunatly, easyant offers solutions for both cases. The prefered way is to create reusable plugins, however sometimes we you only need it quickly on our project and don’t have time / money / motivation to spend on reusable stuff.
Project specific logic is implemented in an ant build file module.ant by default at same level of your module.ivy file.
<project name="my-custom-stuff">
<echo>This message will be printed at startup </echo>
<target name="hello">
<echo>Hello world printed from our custom hello target</echo>
</target>
</project>
Invoking hello target will display our message.
> easyant hello
Powerful isn’t it ? EasyAnt can print messages !
Ok you seem sceptical. This is useless if we can’t interact with existing targets in easyant.
Depending on an existing target
First, you can depend on existing targets or extension points.
<target name="hello2" depends="package-jar:jar">
<echo>Hello world executed after package-jar:jar target </echo>
</target>
Invoking hello2 target will trigger package-jar:jar target and display our message. But if you invoke other target, hello2 target will never be called has no one depends on it.
This is what almost every one knows about ant. But ant provides a solution for this: Extension Point. Do you know what Extension point is ?
Definition of Extension Point
Extension-Points are similar to targets in that they have a name and a depends list and can be executed from the command line. Just like targets they represent a state during the build process.
Unlike targets they don’t contain any tasks, their main purpose is to collect targets that contribute to the desired state in their depends list.
Targets can add themselves to an extension-points’s depends list via their extensionOf attribute. The targets that add themselves will be added after the targets of the explicit depends-attribute of the extension-point, if multiple targets add themselves, their relative order is not defined.
The main purpose of an extension-point is to act as an extension point for build files designed to be imported. In the imported file an extension-point defines a state that must be reached and targets from other build files can join the depends list of said extension-point in order to contribute to that state.
Original idea was from early stages of easyant is now part of Ant since 1.8.0.
Integration of extensionPoint in EasyAnt
EasyAnt comes with a default lifecycle. This default lifecycle is a set of predefined extension points for the common needs.
Each phase is considered an essential step of the build process.
Note : Even if EasyAnt provides you a default lifecycle we never lock you in. So you’re able to add your own extension points or override existing ones.
Plugins can provide additionnal extension points. Plugins typically add low-level tasks to one or more extension-points. For example, a plugin can contribute to processing sources before compilation, you will in that case plug your own target to abstract-compile:compile-ready extension-point. This contributes to have a dynamic lifecycle.
When using easyant from the command line, you can use ProjectMan commands to get informations on available properties, targets or extensionPoints.
Invoking the following command will display available extensionPoints in your project.
> easyant -listExtensionPoints
Depending on an existing extension point
Getting back to our example could we plug our hello target to compile step ?
<target name="hello3" depends="compile">
<echo>hello world displayed when compile extension point is reached</echo>
</target>
Calling any target depending on compile (part of the default lifecycle) will trigger hello3 target execution.
> easyant package
Will result :
...
[echo] This message will be printed at startup
...
...
compile-java:compile:
[mkdir] Created dir: /home/neoverflow/projects/easyant/community-plugins/projects/easyant-examples/project-specific-logic/target/main/classes
[javac] Compiling 1 source file to /home/neoverflow/projects/easyant/community-plugins/projects/easyant-examples/project-specific-logic/target/main/classes
hello3:
[echo] hello world displayed when compile extension point is reached
...
package-jar:jar:
[jar] Building jar: /home/neoverflow/projects/easyant/community-plugins/projects/easyant-examples/project-specific-logic/target/artifacts/project-specific-logic.jar
Integrating a missing feature : Code Coverage
So now we’re done with theory, we know how extension points work in Ant. I need to solve a problem specific to my project: measuring the code coverage of my tests with cobertura.
How could we integrate cobertura ant task in our module.ant file easily ?
Fetch cobertura and configure it
Usually this is done by copying manually cobertura.jar in $ANT_HOME/lib or in $USER_HOME/.ant/lib.
EasyAnt is based also on Apache Ivy therefore a quick search of cobertura on http://search.maven.org show us the ivy syntax to depend on cobertura.
<dependency org="net.sourceforge.cobertura" name="cobertura" rev="1.9.4.1"/>
But this is not a project dependency ! You don’t need it to package your project, you only need this dependency to run code coverage. Can ivy ant tasks help us here ? The answer is yes by using cachepath task. This task constructs an ant path consisting of artifacts in ivy cache for a resolved module.
Let us update our module.ant file to resolve the dependency, fill an ant classpath and configure cobertura.
<target name="cobertura:init">
<ivy:cachepath pathid="cobertura.classpath" inline="true" organisation="net.sourceforge.cobertura" module="cobertura" revision="1.9.4.1" conf="default" settingsRef="easyant.ivy.instance"/>
<taskdef classpathref="cobertura.classpath" resource="tasks.properties" />
</target>
Note the presence of settingsRef attribute. EasyAnt uses two ivy instances :
- used to resolve/retrieve EasyAnt modules (which can be buildtypes/ plugins or skeletons) dependencies
- used to resolve/retrieve project dependencies
There is a strong separation of context, this means that plugins dependencies will not leak in your project. Both instance are configurable.
- Project ivy instance can be configured through an ivysettings file defined with properties. Click here if you want more details.
- EasyAnt ivy instance can be configured through an ivysettings file defined in easyant-config. Click here if you want more details.
Perform coverage instrumentation
Now our problematic is to run coverage instrumentation, and integrate it with existing stuff in easyant.
Instrumentation needs to be done on compiled classes, so our task will depend on “compile” extension-point.
Then we could either “hardcode” some informations (path to compiled classes), or reuse easyant properties.
You can find all properties available in your project by using the following ProjectMan command :
> easyant -listProp
So here we will reuse the following properties / classpath
- Property : target.test.classes
- Property : target.integration.test.classes
- Path : run.test.classpath
<target name="cobertura:instrument" depends="cobertura:init,compile,abstract-test:init">
<property name="coverage.dir" value="${target}/coverage"/>
<property name="coverage.datafile" value="${coverage.dir}/cobertura.ser"/>
<mkdir dir="${coverage.dir}"/>
<!-- delete previous coverage data file -->
<delete file="${coverage.datafile}" />
<!-- do instrumentation -->
<cobertura-instrument todir="${coverage.dir}" datafile="${coverage.datafile}">
<fileset dir="${target.test.classes}"/>
<fileset dir="${target.test.integration.classes}"/>
</cobertura-instrument>
<!-- contribute to test runtime classpath and prepend instrumented classes -->
<ea:path pathid="run.test.classpath" overwrite="prepend">
<fileset dir="${coverage.dir}"/>
</ea:path>
</target>
Do reporting
<target name="cobertura:run" depends="cobertura:instrument">
<cobertura-report format="html" destdir="${target.report.dir}" srcdir="${src.main.java}" datafile="${coverage.datafile}"/>
</target>
That’s all, you’re now able to run code coverage in your project.
You can find the code of this example with project specific logic on GitHub.
Next article : We will refactor or module.ant to create a cobertura plugin.
March 20th, 2013 by Jean-Louis Boudart
After months of work, many improvements and bugfixes, a release, EasyAnt is graduated and will leave Apache Incubator in a couple of days.
The project will become a subproject of Ant (as Ivy did in the past).
The following things will change :
The svn tree
We will move the svn tree of EasyAnt under Ant’s one. Everything except ‘KEYS’ and ‘site’ under http://svn.apache.org/repos/asf/incubator/easyant/ will move into http://svn.apache.org/repos/asf/ant/easyant .
We’ll give write rights to EasyAnt committers on the entire Ant svn tree.
The website
EasyAnt website is using the same publication mechanism as Ant. We’ll need to move the svn tree of the site from http://svn.apache.org/repos/asf/incubator/easyant/site/ to http://svn.apache.org/repos/asf/ant/site/easyant . The web site will be at http://ant.apache.org/easyant
A redirection will be set from incubator/easyant to ant.apache.org/easyant
The mailing lists
- easyant-dev@ will be closed in favor of dev@ant.apache.org
- easyant-commits@ will be closed in favor of notifications@ant.apache.org
- easyant-private@ just closed.
Jira
No need to change anything, we will use the same : https://issues.apache.org/jira/browse/EASYANT
We will keep you posted once the migration is over.
Congrats again to the team !
EDIT The migration is over !
March 5th, 2013 by Jean-Louis Boudart
In the course of this write up, you will be taken through basics of EasyAnt and a simple-and-live example of setting up an EasyAnt web application project. Prerequisite to your setting up an Easyant project means you have to have the Easyant environment correctly configured. The only thing you need to do to use easyant is to set the EASYANT_HOME property.
You should first set up in your environment the EASYANT_HOME variable :
- for windows users : set EASYANT_HOME=c:\path\to\easyant
- for unix users : export EASYANT_HOME=/path/to/easyant
You may also add EASYANT_HOME to your path :
- for windows users : set PATH=%EASYANT_HOME%\bin;%PATH%
- for unix users : export PATH=$EASYANT_HOME/bin:$PATH
Let us try to setup a java Web Application project.
EasyAnt provides skeleton feature to quickstart projects. It basically creates a projects structure, based on an existing model. You can fortunatly create your own skeleton but we will cover this in future articles.
Selecting available skeleton :
> easyant skeleton:select
-skeleton:select:
[echo] Choose a skeleton in the following list:
[ea:searchmodule] 1: std-skeleton v0.9 (Emtpy skeleton structure)
[ea:searchmodule] 2: std-java-application v0.9 (Skeleton for creating standard java application)
[ea:searchmodule] 3: std-ant-plugin v0.9 (Skeleton for creating ant based plugin for easyant)
[ea:searchmodule] 4: std-java-webapplication v0.9 (Skeleton for creating standard java web application)
[ea:searchmodule] Choose a number: (1, 2, 3, 4)
std-java-webapplication is what we are looking for, now it’s time to answer a few questions :
[input] The path where the skeleton project will be unzipped [.]
[input] Organisation name of YOUR project []
org.mycompany
[input] Module name of YOUR project
myproject
[input] Revision number of YOUR project [0.1]
Few seconds later we have our project ready to use.
A project using EasyAnt MUST contain a file named module.ivy and an optional file named module.ant.
The module.ivy file
This file is the module descriptor of your project. It contains information like your company name, the module name, dependencies, and Easyant build information. This is nearly a regular IVY specification file.
<ivy-module version="2.0" xmlns:ea="http://www.easyant.org">
<info organisation="my.easyant.project" module="my-webapp" status="integration" >
<description>
This project is a sample of a java webapplication
</description>
<ea:build organisation="org.apache.easyant.buildtypes" module="build-webapp-java" revision="0.9"/>
</info>
<configurations>
<conf name="default"/>
<conf name="test" />
</configurations>
<publications>
<artifact type="war"/>
</publications>
</ivy-module>
The above is a standard ivy specification file, other than the ‘ea:build’ tag. To use easyant you must declare the easyant namespace
xmlns:ea="http://www.easyant.org"
Pay attention to the ea:build tag. This tags define which build-type is used for your project. In our case, we intend to set up a standard war so we will use build-webapp-java which provides all the targets necessary to compile / package a webapp application.
Note: The organisation argument in ea:build tag is optional. If not specified easyant will use the default one (org.apache.easyant.buildtypes).
The above file is a sufficient instruction to easyant to build a WAR using the current project. Only, you need to mind the source structure for this build to work.
Source Structure
Similar to Maven, by default, if you are using a standard build type, you need to follow a standard directory structure. This should be as the build type expects to pick different resources to be present in different directories.
Use the following: 
In the above directory structure, all your java sources should go into src/main/java directory. All resources that should move into WEB-INF/classes directory should go inside src/main/resources. Entire src/main/webapp directory moves into the root of the web application WAR. For instance, you may keep WEB-INF directory inside this directory. The module.ivy file should reside inside ‘testproj’ directory. Any external dependencies of your project should be specified inside your module.ivy file, dependencies section.
Building the Project
The project is now ready to be built. You can simply run: easyant. You should see a ‘target’ directory created in your project root. The built war will reside inside the target/artifacts directory. You can go ahead and deploy it in your app-server.
Running default target
Running easyant without arguments will execute the default target of a project.
Example :
> easyant
Running a specific extension point
Running EasyAnt with a extension point name will execute ALL the targets bound to it.
Example:
> easyant package
All targets related to the package extension point will be executed. Supposing your build is composed of several modules that generate packages (jar + source.jar + documentation.jar). All such packages will be generated. If your need is just to create the first jar, maybe you should call the explicit target instead.
Running a specific target
Running EasyAnt with a target name or a list of names will execute only the specified targets.
Example:
> easyant package-jar:jar
Displaying project help
Running EasyAnt with “-p” argument will display a project help (ie. show all extension point / target available)
Example:
> easyant -p
Adding dependencies
Dependencies are defined in the module.ivy files. There is a section dedicated to dependencies Let’s consider that our project needs an artifact named foo provided by acme in revision 2.0 The dependencies section will look like this :
<dependencies>
<dependency org="acme" name="foo" rev="2.0" conf="default"/>
</dependencies>
If you want to have more informations on dependencies please refer to the official ivy documentation
Adapt it to your need
Almost everything is configurable through properties in easyant. Suppose we want to have the generated artifacts in “dist” directory instead of “target/artifacts”. We will add additional informations :
<ea:build organisation="org.apache.easyant.buildtypes" module="build-std-java" revision="0.9"/>
<ea:property name="target.artifacts" value="dist"/>
</ea:build>
Running “easyant” will generate the output war in “dist” directory.
Now we want to force java 1.5 compatibility at compile time. We will add additionnal property :
<ea:build organisation="org.apache.easyant.buildtypes" module="build-std-java" revision="0.9"/>
<ea:property name="target.artifacts" value="dist"/>
<ea:property name="compile.java.target.version" value="1.5"/>
</ea:build>
Add additionnal plugin
EasyAnt provides plugins that you can selectively choose to use in your project. These provide you convenience functionalities. E.g. Quick WAR deployments in Jetty, Xooki documentation, Coverage tools etc. In this tutorial, let us quickly take a look over how we may integrate Jetty with our current war. Let us first include a ‘Hello World’ index.htm inside the src/main/webapp directory. These are the contents of our index.htm:
<html>
<head></head>
<body>
<h3>Hello World !!</h3>
</body>
</html>
Our module.ivy is the repository of all plugins that our project uses. So, we go ahead and include the Jetty plugin in our module.ivy.
<ivy-module version="2.0" xmlns:ea="http://www.easyant.org">
<info organisation="my.easyant.project" module="my-webapp" status="integration" >
<description>
This project is a sample of a java webapplication
</description>
<ea:build organisation="org.apache.easyant.buildtypes" module="build-webapp-java" revision="0.9">
<ea:plugin organisation="org.apache.easyant.plugins" module="jetty-deploy" revision="0.9"/>
</ea:build>
</info>
<configurations>
<conf name="default" />
<conf name="test" />
</configurations>
<publications>
<artifact type="war"/>
</publications>
<dependencies>
<dependency org="acme" name="foo" rev="2.0" conf="default"/>
</dependencies>
</ivy-module>
Note the addition of the ea:plugin tag. The above line instructs easyant to use the jetty-deploy plugin in version 0.9 in the current project.
Note: The organisation argument in ea:plugin tag is optional. If not specified easyant will use the default one (org.apache.easyant.plugins).
The jetty-deploy module exposes a target called ‘jetty-deploy:run’. Further, this target depends on package-war:war of EasyAnt, which means that by the time this target is executed, the WAR would have been created and available for deployment on Jetty. Because, in the new line added to module.ivy, the jetty-deploy module was added you can run ‘easyant jetty-deploy:run’ to build and package your web application, and deploy it on jetty. The command launches jetty, and keeps displaying Jetty logs on console. You can now access your web application on browser. Try hitting http://localhost:8080 !
module.ant
If you want to add something to the default build types that come packaged with EasyAnt, you can write a module.ant file in your project root. This is called before EasyAnt executes any of its core build scripts. You can also include any convenience targets you find useful, that are specific to your project and do not come included in EasyAnt. This will be covered in future article.
Going further ?
If you want more information we strongly recommend you to read the Module files documentation.
March 5th, 2013 by Jean-Louis Boudart
The Apache EasyAnt project is pleased to announce its 0.9-incubating release.
Apache Easyant is a toolbox focusing on easing project build processes.
It’s based on Apache Ant and Apache Ivy, and allows for maximum flexibily, improved integration in existing build systems and provides conventions and guidelines.
Our goals are :
- to leverage popularity and flexibility of Ant.
- to integrate Apache Ivy, such that the build system combines a ready-to-use dependency manager.
- to simplify standard build types, such as building web applications, JARs etc, by providing ready to use builds.
- to provide conventions and guidelines.
- to make plugging-in of fresh functionalities as easy as writing Ant scripts.
To still remain adaptable,
- Though EasyAnt comes with a lot of conventions, we never lock you in.
- EasyAnt allows you to easily extend existing modules or create and use your own modules.
- EasyAnt makes migration from Ant very simple. Your legacy Ant scripts could still be leveraged using EasyAnt.
Key features of this 0.9-incubating release are :
- dynamic project lifecycle to remain even more flexible (get rid of phases in favor of extension point)
- enhanced multimodule support
- enhanced exception handling
- support for offline mode
- new command line switches and related api to list and describe targets, properties, extensionPoints and even parameters (path, filesets)
- plugin dependencies can be overridden in module descriptors
- a set of new ant tasks to make plugin writer life easier
- a lighter distribution with only core plugins/buildtypes
- online repository for others plugins/buildtypes/skeletons
- upgrade to Apache Ant 1.8.4 and Apache Ivy 2.3.0
- numerous bug fixes as documented in Jira and in the release notes
This is the first EasyAnt release under Apache Software Foundation.
You can download this 0.9-incubating release at:
http://incubator.apache.org/easyant/download.cgi
Issues should be reported to:
https://issues.apache.org/jira/browse/EASYANT
More information can be found on the website:
http://incubator.apache.org/easyant/
June 7th, 2011 by Siddhartha Purkayastha
A few weeks back, I had been wondering on support for diagnostic functionality for EasyAnt. Trying to search for a starting point, I was drawn to Ant Diagnostics. Try this out:
ant -diagnostics
The output is interesting. Ant scans and lists quite a few helpful setup and environment bits, including the ant version, Ant libraries, a number of system properties etc. Such information is quite helpful when troubleshooting setup or environment issues. But – what if problems being faced are actually problems with the scripts themselves?
Would debugging be more useful in such cases? So there is an effort to build a debugger, that can be driven from the command line itself.
The debugger is built into a separate jar, that you can add to the Ant classpath (use the -lib argument). The debugger library essentially contains a simple build listener that pauses build execution at breakpoints, that you can specify through a debug prompt (that you get when you run the build with the debug listener). There are a list of debug commands that you can issue from this prompt and inspect the state of your build.
- break <target>: Adds a breakpoint at a target
- watch <property>: Adds a watchpoint at a property
- inspect property <property.name>: Shows the current value of a property
- inspect path <some.path>: Shows the current value of a path
- locate property <property.name>: Shows the exact location of the property declaration in build files
- return: Resumes the build execution
An initial POC is in place and can be found here: https://svn.apache.org/repos/asf/incubator/easyant/tasks/trunk/command-line-debugger. You should find a README file at this location with instructions on how to try it out. Currently, it does not have any step through functionality. The build may be paused – you may inspect as much as you wish, and you can then resume the build.
The following are planned:
- Break points at specified exceptions
- Way to get information on all set breakpoints and watchpoints
- Way to set / unset / create new properties
While there are Ant debuggers in IDEs (I dont have much personal experience using them), hopefully this one will help some command line users.
April 12th, 2011 by Jean-Louis Boudart
As you should know EasyAnt project is currently moving to Apache Incubator.
We already migrated sources1, issues2, and mailing lists3.
It’s now time to migrate our website and our blogs.
Our new website is hosted at http://incubator.apache.org/easyant/, we will make a permanent redirection of http://www.easyant.org to this new url in a few weeks.
EasyAnt’s blog moves to http://blog.easyant.org. Old blog post has been imported.
Our new blog will acts as official blog and will also acts as aggregator for community blogs talking about easyant.
It’s time to update your bookmarks.
[1] https://svn.apache.org/repos/asf/incubator/easyant/
[2] https://issues.apache.org/jira/browse/EASYANT
[3] http://incubator.apache.org/easyant/Mailinglist.html
March 17th, 2011 by Jean-Louis Boudart
Apache-Easyant is now on Twitter.
You can follow us @ApacheEasyant if you want fresh news of the project.
February 1st, 2011 by Jean-Louis Boudart
The EasyAnt project has been successfully being voted to enter the Apache Incubator and Apache Ant is sponsoring it.
The EasyAnt project aims to leverage the popularity and flexibility of both Ant and Ivy in order to provide an easy to use build system. EasyAnt will provide ready to use ant scripts to build standard java applications or webapps just like usual Maven users are used to. It will still remain adaptable by offering a property based configuration. And even more as you will be able to easily extend existing modules or create your own ones.
You can read the more detail proposal at http://wiki.apache.org/incubator/EasyAntProposal
December 20th, 2010 by Jérôme Benois
As I said in my previous post,
the Bushel source code is now part of the Apache Ivy code base. The integration
task #IVY-1241 is
fully complete.
Now it's possible to build OSGi bundles / eclipse plugins with Ant + Ivy. It
also supports provisionning from an OBR (OSGi Bundle Repository).
You can found more details in this documentation : http://ant.apache.org/ivy/history/trunk/osgi.html
Don't hesitate to contact me for exchange any feedbacks.
December 20th, 2010 by Jérôme Benois
As I said in my previous post,
the Bushel source code is now part of the Apache Ivy code base. The integration
task #IVY-1241 is
fully complete.
Now it's possible to build OSGi bundles / eclipse plugins with Ant + Ivy. It
also supports provisionning from an OBR (OSGi Bundle Repository).
You can found more details in this documentation : http://ant.apache.org/ivy/history/trunk/osgi.html
Don't hesitate to contact me for exchange any feedbacks.