Ant jar task include a single class file only - java

i have an ant task
<target name="create_jar" depends="compile">
<jar destfile="build/temp/MyClassJar.jar" basedir="build/classes/com/company/utils">
<manifest>
<attribute name="Main-Class" value="com.company.utils.MyClass"/>
</manifest>
</jar>
</target>
the folder build/classes has multiple packages and class files but in my jar i only want to include only two files MyClass.class and MyClass$1.class which are in com/company/utils folder.
if i have base-dir as com/company/utils when i run the task the jar does not have the package folders in like com/company/utils is not created inside the jar file but if i change my base-dir to build/classes then all the files are getting included.
what do to fix this.

The Jar task takes a nested fileset, so you can do this:
<jar destfile="build/temp/MyClassJar.jar">
<fileset dir="build/classes" includes="**/MyClass*.class" />
<manifest>
<attribute name="Main-Class" value="com.company.utils.MyClass"/>
</manifest>
</jar>

Related

How can I use Ant to build a single executable .jar that has dependency .jars in it in a /lib dir in the .jar?

How can I use Ant to build a single executable .jar that has dependency .jars in it in a /lib dir in the .jar?
I have a /lib directory in the project root file that contains all the binary dependency .jars.
In java an executable jar has a specially formatted manifest, that includes the following attributes:
Main-Class
Class-Path
In ANT this is easily accomplished as follows with the jar task:
<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}" includes="*.class">
<manifest>
<attribute name="Main-Class" value="${main-class}" />
<attribute name="Class-Path" value="${jar-classpath}" />
</manifest>
</jar>
For extra credit one can use the very useful manifestclasspath task to help assemble the correct classpath string.
<manifestclasspath property="jar-classpath" jarfile="${jar.dir}/${ant.project.name}.jar">
<classpath>
<fileset dir="/path/to/lib/dir" includes="*.jar"/>
</classpath>
</manifestclasspath>

How to a jar file include another jar via Ant?

I have 'test.jar' . I want to create 'my.jar' . I want my.jar include test.jar
My code:
<target name="jar" >
<copy file="${conf.dir}/default.xml" todir="${build.classes}" />
<jar jarfile="${build.dir}/test.jar" basedir="${build.classes}">
<manifest>
</manifest>
</jar>
</target>
<target name="services-jar">
<jar jarfile="${build.dir}/my.jar">
<manifest>
<attribute name="Main-Class" value="mypackage.MyClass" />
<attribute name="Class-Path" value="${build.dir}/test.jar" />
</manifest>
</jar>
</target>
If I run 'my.jar' : java -jar my.jar
display message: Could not find or load main class mypackage.MyClass
My MANIFEST.MF file:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.4
Created-By: 1.7.0_17-b02 (Oracle Corporation)
Main-Class: mypackage.MyClass
Class-Path: ./build/test.jar
Any idea?
The paths in the manifest Class-Path need to be relative to the location of the JAR file that contains the manifest. Since both my.jar and test.jar are in the same directory (${build.dir}) the relative path is simply test.jar, i.e. you need
<jar jarfile="${build.dir}/my.jar">
<manifest>
<attribute name="Main-Class" value="mypackage.MyClass" />
<attribute name="Class-Path" value="test.jar" />
</manifest>
</jar>
More generally, you may wish to look up the <manifestclasspath> task which, given the location of the target JAR file and a set of other JARs that you want to put on the Class-Path, calculates all the relative paths for you and generates the correct value for the manifest attribute.
You are mixing separators. Replace your"${build.dir}\test.jar" with "${build.dir}/test.jar".

'Could not find the main class error' in a build file

I have craated a Java application with an Ant build file containing the jar-task task that generate a jar file from the application.
<target name="jar-task" depends="compile">
<mkdir dir="${jar.dir}"/>
<jar destfile="jar/guix.jar" basedir="${bin.dir}">
<fileset dir="${basedir}">
<include name="${basedir}/images/**/" />
</fileset>
<manifest>
<attribute name="Main-Class" value="IO.Deep.clk.GUI"/>
<attribute name="Class-Path" value="${basedir}/SPLASH-2.0.0.jar ${basedir}/lib/dist/* ${basedir}/user.properties"/>
</manifest>
<filelist dir="${basedir}" files="user.properties"/>
</jar>
</target>
When I execute on the command line however a NoClassDefFoundError stating
Could not find the main class IO.Deep.clk.GUI. Program will exit.
Now, the GUI file is exactly in the specific folder and in the same package, I really can't understand where the error may be...can anyone help?
The name images suggests, that the jar file will contain only images. But where is the actual code?
<fileset dir="${basedir}">
<include name="${basedir}/images/**/" />
</fileset>
This piece
<attribute name="Class-Path" value="${basedir}/SPLASH-2.0.0.jar ${basedir}/lib/dist/* ${basedir}/user.properties"/>
will write full qualified pathnames into the manifest. Are sure, that this is correct? Also note, that the code will not find user.properties by putting the file on the classpath. The classpath can contain only directories or jar-files in which classes or other stuff will be searched for. But simple files won't work.
I'm also not sure about the lib/* part. Is the class IO.Deep.clk.GUI in one of the jar files in that directory? That would be a hint, that all directories must be listed explicitly. If that's not a problem - good.
EDIT:
The classpath problems can be avoided by adding the task manifestclasspath (Ant docs) before the call of jar and by using the generated classpath value inside the manifest attribute. Outline:
<manifestclasspath property="jar.class.path" jarfile="jar/guix.jar">
<classpath>
<fileset dir="." includes="*.jar" />
<fileset dir="." includes="lib/*.jar" />
</classpath>
</manifestclasspath>
<echo message="Class-Path will be: ${jar.class.path}" />
<jar ....>
....
<attribute name="Class-Path" value="${jar.class.path}" />
Are you sure your resulting filest inside the jar task contains all the files you need?
For debugging you can use a path convert to the fileset out of the jar task and echo it so that you can verfiy that you have the correct files. If this is OK then I don't see something else wrong in your file although I have limited experience with the jar task myself.

Building(With ant) a jar with it's main in the default package

I was wondering if anyone knew how to set the Main-class property in an Ant Build xml to look in the default package? I've tried just "Main", but it doesn't seem to find it.
You should use Main-Class attribute of manifest:
<jar jarfile="${jar.name}">
<fileset dir="${classes.dir}">
<include name="**/*.*"/>
</fileset>
<manifest>
<attribute name="Main-Class" value="MyApp"/>
</manifest>
</jar>
Docs for Ant Jar Task

Problem running a Jar file

I've compiled a java project into a Jar file, and am having issues running it.
When I run:
java -jar myJar.jar
I get the following error
Could not find the main class: myClass
The class file is not in the root directory of the jar so I've tried changing the path of the main class to match the path to the class file and I get the same issue.
Should I be flattening the file structure? if so how do I do this. I'm using Ant to build the Jar file if thats of any use.
UPDATE
Here is the contents of the jar and the relevant Ant sections, I've changed the name of the firm I work for to "org":
META-INF/
META-INF/MANIFEST.MF
dataAccessLayer/
dataAccessLayer/databaseTest.class
org/
org/eventService/
org/eventService/DatabaseObject.class
org/eventService/DatabaseObjectFactory.class
org/eventService/DbEventClientImpl$HearBeatMonitor.class
org/eventService/DbEventClientImpl.class
org/eventService/EmptyQueryListException.class
org/eventService/EventHandlerWorkItem.class
org/eventService/EventProcessor.class
org/eventService/EventTypeEnum.class
org/eventService/EventWorkQueue$MonitorThread.class
org/eventService/EventWorkQueue$PoolWorker.class
org/eventService/EventWorkQueue.class
org/eventService/FailedToLoadDriverException.class
org/eventService/IConnectionFailureListener.class
org/eventService/InvalidEventTypeException.class
org/eventService/JdbcInterfaceConnection.class
org/eventService/NullArgumentException.class
org/eventService/OracleDatabaseObject.class
org/eventService/ProactiveClientEventLogger.class
org/eventService/ProactiveClientEventLoggerException.class
org/eventService/PropertyMap.class
org/eventService/SQLServerDatabaseObject.class
org/eventService/TestHarness.class
org/eventService/Utilities.class
And the ant target:
<target name="compile" depends="init" description="compile the source ">
<javac srcdir="src" destdir="bin" classpathref="project.class.path"/>
</target>
<target name="buildjar" description="build jar file" depends="compile">
<mkdir dir="dist"/>
<jar destfile="dist/myJar.jar" basedir="bin" includes="**/*.class" >
<manifest>
<attribute name="Main-Class" value="org.eventService.ProactiveClientEventLogger"/>
</manifest>
</jar>
</target>
In your manifest file, make sure you have the attribute Main-Class set to the name of the class containing your main() method. For example, if the package-qualified name of the class is my.cool.Class, then, in your JAR manifest, Main-Class should be set to my.cool.Class.
Also made sure that you have a package declaration in your .java files (for example, in Class.java, make sure you have the proper package my.cool; declaration). Also, make sure your directory hierarchy is set up correctly (my.cool.Class should be in $SRC/my/cool/Class.java).
You should specify your main class during jar creation with full path, something like:
<target name="jar" depends="compile">
<delete file="myJar.jar"/>
<delete file="MANIFEST.MF"/>
<manifest file="MANIFEST.MF">
<attribute name="Main-Class" value="my.package.myClass"/>
</manifest>
<jar destfile="myJar.jar"
basedir="."
includes="**/*.class"
manifest="MANIFEST.MF" />
</target>

Categories