Creating an ear-File with ant - ant

I am new to ant i referred many sites , i need to build.xml for my project which consists
of two modules i have application.xml file which represents corresponding war file
so my question is it sufficient to add the application.xml file
<ear destfile="${dist.dir}/${ant.project.name}.ear" appxml="${conf.dir}/application.xml">
<metainf dir="${build.dir}/META-INF"/>
<fileset dir="${dist.dir}" includes="*.jar,*.war"/>
</ear>
whether this will refer the corresponding war files or i need to compile the whole scenario please let me know. how solve this.

I'm not 100% sure what you're asking.
In order to use the <ear> task, you already need to have compiled the required jars and wars.
If those jars and wars have already been built, you simply refer to them in your <ear> task as you did in your example. The application.xml must already exist before you build your ear. The application.xml doesn't build the jars and wars, you have to do that.
If you haven't already built the wars and jars, you need to do that first. A general outline of a build.xml looks something like this:
<project name="foo" basedir="." default="package">
<!-- Some standard properties you've defined -->
<property name="target.dir" value="${basedir}/target"/>
<property name="xxx" value="yyy"/>
<property name="xxx" value="yyy"/>
<property name="xxx" value="yyy"/>
<!-- Compile properties that allow overrides -->
<property name="javac.nowarn" value="false"/>
<property name="javac.listfiles" value="false"/>
<property name="javac.srcdir" value="source"/>
<property name="javac.distdir" value="${target.dir}/classes"/>
<target name="clean"
description="cleans everything nice and shiny">
<delete dir="${target.dir}"/>
</target>
<target name="compile"
description="Compiles everything">
<mkdir dir="${javac.distdir}"/>
<javac srcdir="${javac.srcdir}"
destdir="${javac.destdir}"
[...]
[...]/>
</target>
<target name="package.jar"
depends="compile"
description="Package jarfile">
<jar destfile="${target.dir}/jarname.jar"
[...]
[...]/>
</target>
<target name="package.jar2"
depends="compile"
description="Package jarfile">
<jar destfile="${target.dir}/jarname2.jar"
[...]
[...]/>
</target>
<target name="package.war"
depends="compile"
description="Package jarfile">
<war destfile="${target.dir}/jarname.jar"
[...]
[...]/>
</target>
<target name="package"
depends="package.jar"
description="Make the ear">
<ear destfile="${target.dir}/earfile.ear"
[...]/>
</target>
</project>
Basically, it consists of a bunch of targets and each target does one task. You can have targets depend upon other targets. For example, this particular build.xml will automatically run the package task. The package task depends upon the package.jar task which depends upon the compile task. Thus, the build.xml file will first call compile, then package.jar, then package.
The important thing to remember is that you don't specify the order of the events. You let Ant figure that out, and you let Ant figure out what you need to do. Let's say you've modified a java source file. Ant knows that it has to recompile only that one file. It also knows that it might have to rebuild the jarfile that contains that classfile. And, it then knows it has to rebuild the ear. Most tasks can figure it out on their own, and you don't do a clean for each build. (You notice that the clean target isn't called by package or compile. You have to call it manually).
The only other thing I recommend is that you try to keep your work area clean. Any files you create should be put into the ${target.dir} directory. That way, when you do a clean, you only have to delete that one directory.
I hope this answer your question.

Related

is there a way to make a jar with the Eclipse generated ant script?

To my surprise the build.xml file generated by Eclipse (Neon) for Java has no element containing an invocation of a jar task. As often is the case with code generation I think you have to use it and make no edits so that you can regenerate - or - avoid code generation completely. A comment in the generated file suggests it might be possible to avoid edits by extending the capabilities by importing.
<!-- WARNING: Eclipse auto-generated file.
Any modifications will be overwritten.
To include a user specific buildfile here, simply create one in the same
directory with the processing instruction <?eclipse.ant.import?>
as the first entry and export the buildfile again. -->
I thought I would be able to use the <?eclipse.ant.import?> element in an second file called export.xml. In ant scripting there is supposed to be one project per buildfile so now there is a second project with a dependency on a target in the first project.
Regenerating build.xml reveals that it contains an "import" as expected.
<import file="export.xml"/>
Unfortunately this does not work. Running ant, which I do from the command line, just seems to result in the export/jar project being ignored.
The generated script with the import element (nested on the 7th line)...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="build" name="ohana1">
<property environment="env"/>
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.8"/>
<property name="source" value="1.8"/>
<import file="export.xml"/>
<path id="ohana1.classpath">
<pathelement location="bin"/>
<pathelement location="../export/ohana1/commons-collections-3.2.1.jar"/>
</path>
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.launch"/>
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="build-subprojects,build-project" name="build"/>
<target name="build-subprojects"/>
<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}"/>
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="ohana1.classpath"/>
</javac>
</target>
<target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/>
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
<copy todir="${ant.library.dir}">
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</copy>
<unzip dest="${ant.library.dir}">
<patternset includes="jdtCompilerAdapter.jar"/>
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</unzip>
</target>
<target description="compile project with Eclipse compiler" name="build-eclipse-compiler">
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<antcall target="build"/>
</target>
</project>
The export.xml file meant to make a jar...
<?eclipse.ant.import?>
<project basedir="." default="export" name="ohana1Export">
<target depends="build,make-jar" name="export"/>
<target name="make-jar">
<jar destfile="../export/ohana1/${ant.project.name}.jar" basedir="bin"/>
</target>
</project>
Note that the Eclipse Ant editor complains about this export.xml file because the target named build, which is a dependency, does not exist in this project/buildfile. The build target is in the generated build.xml. That error might be coming from a "dumb" editor so I went ahead to do a run of ant. Invoking ant from the command line I find that there is no jar file made.
Should I conclude that Eclipse's ant script generator is useless if you need to export a .jar file and that a human should maintain the ant script that meets all the requirements?
Yes, in my opinion the exported build.xml is useless, as of Eclipse Neon, if the intention is to make a .jar.
Specifically do the following.
Manually write the trivial ant script that exports a .jar. The link at the bottom of this post has verbatim text on what the script might look like. You can use the built-in Xml Editor via New > Other > XML > XML File to create this new file which might be called makeJar.xml and save it. If the icon shown in the Package Explorer is still a plain XML file icon refreshing the project may change the icon to an Ant file icon. In the future, you can use Open With to get the Ant Editor instead of the XML Editor. This script will replace the manual exporting of a .jar that the user would otherwise perform via Eclipse.
This script can be added to Project > Properties > Builders. It would be placed second in the list of Builders. First in the list of Builders is the Java Builder which should already exist. When an Eclipse build is invoked the entire list of Builders will be processed in the order shown in the list of Builders. Thus not only will .class files be generated but also the .jar.
What is achieved is greater automation since the .class generation and .jar generation are now integrated, which arguably was the point of using the exported build.xml in a failed attempt to generate the .jar.
Here is the dialog at Project > Properties > Builders that you can use to create a new Builder. Select New then select Ant Builder. I gave the name makeJar to the new Builder.
Here is the dialog for the new Ant Builder that will allow you to browse to your buildfile which is your manually written Ant script that creates a .jar file. In this example the script is makeJar.xml. It also allows you to browse to the base directory to be used when the script is run.
After setting up the new Builder, a project "clean" or project "build" will create .class files and also the .jar.
Eclipse's documentation on this subject is at the link. Note that it seems impossible to link the exact page that contains the instructions so you have to browse down the documentation tree to the section about "Ant buildfiles as project builders".
Link to Eclipse and Ant

ANT: ways to include libraries and license issues

I have been trying to use Ant to compile and ready a project for distribution. I have encountered several problems along the way that I have been finally able to solve but the solution leaves me very unsatisfied. First, let me explain the set-up of the project and its dependencies.
I have a project, lets call it Primary which depends on a couple of libraries such as the fantastic Guava. It also depends on another project of mine, lets call it Secondary. The Secondary project also features some dependencies, for example, JDOM2. I have referenced the Jar I build with Ant in Primary.
Let me give you the interesting bits of the build.xml so you can get a picture of what I am doing:
<project name="Primary" default="all" basedir=".">
<property name='build' location='dist' />
<property name='application.version' value='1.0'/>
<property name='application.name' value='Primary'/>
<property name='distribution' value='${application.name}-${application.version}'/>
<path id='compile.classpath'>
<fileset dir='libs'>
<include name='*.jar'/>
</fileset>
</path>
<target name='compile' description='Compile source files.'>
<javac includeantruntime="false" srcdir="src" destdir="bin">
<classpath refid='compile.classpath'/>
</javac>
<target>
<target name='jar' description='Create a jar file for distribution.' depends="compile">
<jar destfile='${build}/${distribution}.jar'>
<fileset dir="bin"/>
<zipgroupfileset dir="libs" includes="*.jar"/>
</jar>
</target>
The Secodnary project's build.xml is nearly identical except that it features a manifest as it needs to run:
<target name='jar' description='Create a jar file for distribution.' depends="compile">
<jar destfile='${dist}/${distribution}.jar' basedir="${build}" >
<fileset dir="${build}"/>
<zipgroupfileset dir="libs" includes="*.jar"/>
<manifest>
<attribute name="Main-Class" value="lu.tudor.ssi.kiss.climate.ClimateChange"/>
</manifest>
</jar>
</target>
After I got it working, trying for many hours to not include that dependencies as class files but as Jars, I don't have the time or insight to go back and try to figure out what I did wrong. Furthermore, I believe that including these libraries as class files is bad practice as it could give rise to licensing issues while not packaging them and merely including them in a directory along the build Jar would most probably not (And if it would you could choose not to distribute them yourself).
I think my inability to correctly assemble the class path, I always received NoClassDefFoundError for classes or libraries in the Primary project when launching Second's Jar, is that I am not very experienced with Ant. Would I require to specify a class path for both projects? Specifying the class path as . should have allowed me to simply add all dependencies to the same folder as Secondary's Jar, should it not?
You may use the MANIFEST.MF "Class-Path: " to cross-reference your jars.
If they are all in the same directory this will probably work as follows (using it in both projects!):
<target name='jar' description='Create a jar file for distribution.' depends="compile">
<pathconvert property="manifest.classpath" pathsep=" ">
<path refid="compile.classpath" />
<flattenmapper />
</pathconvert>
<jar destfile='${build}/${distribution}.jar'>
<fileset dir="bin"/>
<manifest>
<attribute name="Class-Path" value="${manifest.classpath}"/>
</manifest>
</jar>
</target>
This way you can tell the java runtime environment that your jar needs others to work, expecting them to be in the same directory as the jar you are trying to run.
As a result your primary.jar should have secondary.jar in it's classpath and secondary.jar should have guava.jar in it's classpath.
Another way to create the string may be ants manifestclasspath task (https://ant.apache.org/manual/Tasks/manifestclasspath.html) that can handle subdirectories.
If you are goin to use more and more libraries, you may want to have a closer look at ivy or even maven.

Exclude empty directories with Jar Jar Links

I am using an Ant task from Jar Jar Links to embed classes from a 3rd-party jar file (objenesis) in my distributable jar file (example.jar). Jar Jar will translate classes from the original package (org.objenesis) to one of my choosing.
It works but it leaves empty directories in the distributable jar.
Here is a simplified build.xml:
<target name="jar" depends="compile">
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask"
classpath="lib/jarjar-1.1.jar"/>
<jarjar jarfile="dist/example.jar" excludes="org.objenesis.**">
<fileset dir="build/classes/main"/>
<zipfileset src="lib/objenesis-1.2.jar"/>
<rule pattern="org.objenesis.**" result="org.thirdparty.#1"/>
</jarjar>
</target>
A sample of contents of the example.jar includes (as expected):
org/thirdparty/Objenesis.class
org/thirdparty/ObjenesisBase.class
but also these empty directories (undesirable):
org/objenesis/
org/objenesis/instantiator/
org/objenesis/instantiator/basic/
My question: how to I exclude these empty directories?
I tried the "zap" option (listed in the doc), but that didn't work.
This appears to be a known issue in Jar Jar, listed in their issue tracker: http://code.google.com/p/jarjar/issues/detail?q=empty&id=32
Given that this was raised almost three years ago and doesn't appear to have got any traction, I suppose your options are to contribute a fix, or to work around it.
An example Ant target to work around it, taking advantage of Ant's support for removing empty directories on copy, would be:
<target name="unpolluted-jarjar" description="JarJars without empty directories">
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="${location.lib}/build/jarjar-1.2.jar"/>
<jarjar basedir="${location.classes}" destfile="${location.dist.binaries}/my-app.jar">
<zipfileset src="${location.lib}/shipped/dependency.jar"/>
<rule pattern="com.example.dependency.**" result="com.example.my-app.jarjar.com.example.dependency.#1"/>
</jarjar>
<mkdir dir="${location.dist.binaries}/exploded"/>
<unzip src="${location.dist.binaries}/my-app.jar" dest="${location.dist.binaries}/exploded/my-app.jar"/>
<copy includeemptydirs="false" todir="${location.dist.binaries}/unpolluted/my-app.jar">
<fileset dir="${location.dist.binaries}/exploded/my-app.jar"/>
</copy>
<jar destfile="${location.dist.binaries}/my-app-unpolluted.jar">
<fileset dir="${location.dist.binaries}/unpolluted/my-app.jar"/>
</jar>
</target>
It's a bit grungy, but it achieves what you want.

Location of xsd for ant ivy lib "antlib:org.apache.ivy.ant" for IDE autocomplete with xsd?

I want create Ivy Ant tasks in xml editor in IDE (Intellij iDEA) with autocomplete based on xsd , but I cannot find xsd for register XML namespace xmlns:ivy="antlib:org.apache.ivy.ant"
Where I can find it?
I just copied the ivy jar to INTELLIJ_HOME/lib/ant and now intellij can resolve the ivy tasks.
Or import this ant file to your ant project, its actually the first ivy example in ivy documentation, make sure to always depend on install-ivy target, add your ant file to idea in the ant build window and you dont even have to install ivy and idea recognizes ivy tasks.
<property name="ivy.jar.dir" value="${user.home}/.ivy2/jars" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<property name="ivy.install.version" value="2.2.0" />
<target name="check-ivy-installed" unless="INTERN-ivy.jar.exists">
<available property="INTERN-ivy.jar.exists" file="${ivy.jar.file}"/>
</target>
<target name="download-ivy" depends="check-ivy-installed" unless="INTERN-ivy.jar.exists">
<echo message="downloading and installing ivy"/>
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
<echo message="ivy installed"/>
</target>
<!-- =================================
target: install-ivy
this target is not necessary if you put ivy.jar in your ant lib directory
if you already have ivy in your ant lib, you can simply remove this
target and the dependency the 'go' target has on it
================================= -->
<target name="install-ivy" depends="download-ivy" description="--> install ivy">
<!-- try to load ivy here from local ivy dir, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<echo message="Installing ivy"/>
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
To complete Shalom's answer, the location where to add the ivy.jar for the IntelliJ IDEA Community Edition is INTELLIJ_HOME/lib/ant/lib (one more folder to go).
Maybe it also apply to the full version.
might be, there was no xsd in the past time this discussion started, but at least since may 2011 the ivy scheme is well documented at
http://ant.apache.org/ivy/schemas/ivy.xsd
which is linked right from the documentation in http://ant.apache.org/ivy/
so, to start over using the scheme, you just need:
<?xml version="1.0" encoding="UTF-8"?>
<project name="yourproject"
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"
>
<!-- … -->
I guess this discussion might help you. It appears that there is no xsd for the ivy ant tasks, but Eclipse does autocomplete.
yes, no xsd for ivy ant tasks avialable. but i found the way to make autocomplete in Intellij IDEA
in ant build file need to define additional task:
<property name="ivy.jar.dir" value="C:/Apache/apache-ivy-2.2.0/"/>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant">
<classpath>
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</classpath>
</taskdef>
XML plugin for jEdit defines AntCompleteTask (ant task) that produces an xml file called ant-complete.xml. The resulting file looks as follows:
<element-list>
<!-- ... -->
<element name="classpath"
content="(fileset|dirset|extdirs|existing|filelist|pathelement|path)">
<attribute name="id" type="ID" />
<attribute name="location" type="CDATA" />
<attribute name="cache" type="(true|false|on|off|yes|no)" />
<attribute name="refid" type="CDATA" />
<attribute name="description" type="CDATA" />
<attribute name="path" type="CDATA" />
</element>
<!-- ... -->
The generated file may be downloaded as XML plugin archive. Open XML.jar and browse to xml/completion directory. It's syntax is defined in xml-completion-info.dtd.
The task code does not contain an explicit license, but it's at least GPL. Anyway you probably don't need to distribute that task, only to use it and this doesn't require any license.
I can't assess the usability of the resulting xml file, but jEdit uses it for autocompletion.

Ant build scripts

I am using ant script for generating war file, it will generate the war file. please see the below script
<target name="war" depends="build">
<mkdir dir="${dist}" />
<jar destfile="${dist}/${proj_name}.war" basedir="${build}" />
</target>
If it generates a new war file, then i want to have a property to set the value as "newupdates" otherwise i want to know "noupdates"
A strategy to do this could be to use the UpToDate task to set the property.
You just have to copy the war file to war.bak just after performing the uptodate check, to prepare for the next run.
Another strategy (probably even better) would be to use the UpToDate task to determine if the war has to be generated, setting a property, e.g myuptodateproperty. Then call your war generation target, and make sure it has an if=${myuptodateproperty} constraint, in order not to regenerate the war if it is not needed.
You can use something in the line of (untested code, may need some work):
<target name="war" depends="clean,fillbuildanddist,build">
<mkdir dir="${dist}" />
<uptodate targetfile="${dist}/${proj_name}.war" property="uptodatewar">
<fileset dir="${build}" />
</uptodate>
<antcall target="makewar" />
</target>
<target name="makewar" unless="uptodatewar">
<jar destfile="${dist}/${proj_name}.war" basedir="${build}" />
</target>
With this, the property uptodatewar should be set to true only if the war does not need to be rebuilt, and thus the jar task will only be called in this case. In targets that depend on the war target, you can use the uptodatewar to perform tasks only if the war is new.

Resources