How to perform Ant path mapping in a 'war' task? - java

I have several JAR file pattern sets, like
<patternset id="common.jars">
<include name="external/castor-1.1.jar" />
<include name="external/commons-logging-1.2.6.jar" />
<include name="external/itext-2.0.4.jar" />
...
</patternset>
I also have a 'war' task containing a lib element:
<lib dir="${src.dir}/jars">
<patternset refid="common.jars"/>
<patternset refid="web.jars"/>
...
</lib>
Like this however, I end up with WEB-INF/lib containing the subdirectories from my patterns:
WEB-INF/lib/external/castor-1.1.jar
WEB-INF/lib/external/...
Is there any way to flatten this, so the JAR files appear at the top-level under WEB-INF/lib, regardless of the directories specified in the patterns? I looked at mapper but it seems you cannot use them inside lib.

I was dissatisfied with having to manually generate a WAR directory or declare library subdirectories, so I came up with this. Seems to work, obviously you'll need to adjust it to your own needs:
<war destfile="build/output.war" webxml="${web.dir}/WEB-INF/web.xml">
<fileset dir="${web.dir}" />
<mappedresources>
<fileset dir="${lib.dir}" includes="**/*.jar" />
<chainedmapper>
<flattenmapper/>
<globmapper from="*.jar" to="WEB-INF/lib/*.jar" />
</chainedmapper>
</mappedresources>
</war>

You can try to use mappedresources element (Ant 1.8+)
<mappedresources>
<!-- Fileset here -->
<globmapper from="external/*.jar" to="*.jar"/>
</mappedresources>
http://ant.apache.org/manual/Types/resources.html#mappedresources
If you have a typical web project it is better to split the web-app libraries and general-purpose libraries in different folders and leave WEB-INF/lib to have only those needed at runtime. This way you'll avoid collisions and also your project will look much clearer to other developers.

Related

Does Ant guarantee order of filesets?

in our project we use Ant to distribute files. There is hierarchy of files, and they overwrite files from previous level. Like this: default - level1 - level2. Currently it is made the way:
<copy todir="...">
<fileset dir="${root}/default" includes="**/*" excludes="file1" />
<fileset dir="${root}/level1" includes="**/*" />
<fileset dir="${root}/level2" includes="**/*" excludes="file2"/>
</copy>
So we expected that all the folders contain file with the same name, it will be taken from level2 directory.
Not long ago we moved to a new build box with another version of Java and we discovered that the order of filesets is broken.
Is there a way to fix this issue without modifying ant config files? We have a big number of it. If there is no way, how can I got it off cheap? Thank you.
I don't know if the order of filesets is quaranteed, but the order of copy tasks is.
So, following the suggestion of this answer, it might be a good idea to write several copy tasks with overwrite="true":
<copy todir="...">
<fileset dir="${root}/default" includes="**/*" excludes="file1" />
</copy>
<copy todir="...">
<fileset dir="${root}/level1" includes="**/*" overwrite="true" />
</copy>
<copy todir="...">
<fileset dir="${root}/level2" includes="**/*" excludes="file2" overwrite="true" />
</copy>
You can wrap a sort resource collection around your filesets and ensure the order used by copy this way. Sort itself only likes a single resource collection as child element, so you need to wrap the fileset inside a union or resources container.
See http://ant.apache.org/manual/Types/resources.html#sort
Something like
<sort>
<resources>
<fileset dir="${root}/default" includes="**/*" excludes="file1" />
<fileset dir="${root}/level1" includes="**/*" />
<fileset dir="${root}/level2" includes="**/*" excludes="file2"/>
</resources>
<name/>
</sort>
to sort the files by name.

removing junk folders from a war in build time

I have a web application done several years back, this is done using spring and javascript.
This project we build using the Jidea, IDE.
project have several theme folders which include large amount of images.
after the build the war is so heavy because of these large unused folders and other files.
my question is, is there a method, building tool we can use to remove these junk folders at the build time??
--Rangana
You can use build tools such as Maven or Ant. With these, you can specify exactly what you want to include and what you want to exclude in your war file.
Example with ANT :
<war destfile="dist/MyApp.war" webxml="WebContent/WEB-INF/web.xml">
<fileset dir="WebContent" />
<lib dir="WebContent/WEB-INF/lib" />
<classes dir="build/classes">
<exclude name="config.properties"/>
<include name="**\*.class"/>
<include name="**\*.xml"/>
<include name="**\*.pdf"/>
</classes>
<classes file="config/staging/config.properties"/>
</war>

Ant: Rename sub-directories of the same name

Let's say I have a directory structure like this:
animals/dog/details
animals/cat/details
animals/frog/details
animals/horse/details
Using ant, I would like to rename all sub-directories under animals called details to now be named new. So the result would be this:
animals/dog/new
animals/cat/new
animals/frog/new
animals/horse/new
I've tried something like this:
<move tofile="new">
<path id="directories.to.rename">
<dirset dir="animals">
<include name="**/details"/>
</dirset>
</path>
</move>
But get this error:
Cannot concatenate multiple files into a single file.
You can carry out the rename you describe by means of a mapper. For example:
<move todir="animals">
<dirset dir="animals" includes="**/details" />
<globmapper from="*/details" to="*/new"/>
</move>
(There's a similar example at the end of the move task docs.)
The error you saw arose because you've mixed the single-file mode of the move task (tofile) with multiple-file mode.
There's no need to nest the dirset in a path as the move task accepts any file-based resource collection, including dirset.
Use Ant-Contrib's for task and propertyregex task.
<target name="test">
<for param="detailsDir">
<dirset dir="animals">
<include name="**/details"/>
</dirset>
<sequential>
<propertyregex property="output.dir" input="#{detailsDir}" regexp="(.*)/details" replace="\1" />
<move file="#{detailsDir}" toFile="${output.dir}/new" />
</sequential>
</for>
</target>

Ant File, include another file

Let me describe the scenario first. I have a main build file called main_build.xml. This file calls 4 other build files defined for sub projects, copies the Jars generated by sub project builds and then creates a WAR and finally EAR.
I have my classpath dependencies defined in a XML file named my_clspath.xml.
Now I have two questions:
1. How do I include my_clspath.xml file within the main_build.xml?
2. After including the my_clspath.xml in main_build, how do I make the classpath available for all 4 sub builds which are called from this main_build?.
my_clspath.xml content:
<fileset dir="../myApp_Ear/build/">
<include name="**/*.jar" />
</fileset>
<fileset dir="../myApp_Ear/lib/">
<include name="**/*.jar" />
</fileset>
Try
<project name="Your Project">
<include file="my_clspath.xml" />
<ant antfile="sub1.xml" inheritAll="true" inheritRefs="true" />
</project>
Also, you should set an id on the Filesets. Just having them in your Ant file does not do anything.
<fileset dir="../myApp_Ear/build/" id="my.EAR.fileset">
<include name="**/*.jar" />
</fileset>
Then, in sub1.xml, you can reference the filesets with <fileset refid="my.EAR.fileset" />
Hope this helps.
You should really take a look at the <subant> task. This does exactly what you're asking: You have a master build.xml file that's calling some sub-ant build files to build basic components.

Linked folder not resolved by Ant in eclipse

In my build.xml, below works fine :-
<path id="build.classpath">
<fileset dir="lib [myUtils]" includes="*.jar" />
</path>
if lib [myUtils] is of folder type, but don't works, if it's of Linked Folder type.
Also, I found this when googled :-
https://bugs.eclipse.org/bugs/show_bug.cgi?id=265960
https://bugs.eclipse.org/bugs/show_bug.cgi?id=43081
https://bugs.eclipse.org/bugs/show_bug.cgi?id=265960
Is there any trick to achieve this, without copying the dependencies in work folder??
Note that ant should work outside of eclipse as well. So you can't reply in IDE abstractions. You can use symbolic links (if your OS supports them).
If not, you can use the FileSync plugin to synchronize eclipse project folders with external folders. Or you can simply use the <copy> ant task.
I resolved this using copy task:
<copy todir="target/web/linked1">
<fileset dir="../linkdProject/source1" />
</copy>
<copy todir="target/web/linked2">
<fileset dir="../linkedProject/source2" />
</copy>
....
<war destfile="target/webApp.war">
<fileset dir="WebContent" />
<fileset dir="target/web" /> <!-- copy linked resources -->
...
</war>
<delete dir="target"/>

Categories

Resources