How to a jar file include another jar via Ant? - java

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".

Related

Ant jar task include a single class file only

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>

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>

Load java premain-class from jar library with ANT

Is it possible to load a premain-class from a jar library packed within a jar library? I'have the following setup:
Contets of my library:
# jar -tf myLibrary.jar
META-INF/
META-INF/MANIFEST.MF
agent/
agent/myAgent.jar
com/
com/package/
com/package/subpackage/
com/package/subpackage/A.class
com/package/subpackage/B.class
com/package/subpackage/C.class
Now within my MANIFEST.MF I would like to use something like:
Manifest-Version: 1.0
Premain-Class: com.agentpackage.AgentClass
Class-Path: agent/myAgent.jar
But unfortunately if I "use" this setup with -javaagent:myLibrary.jar it gives me the following error message:
java.lang.ClassNotFoundException: com.agentpackage.AgentClass
FATAL ERROR in native method: processing of -javaagent failed
Is it somehow possible to access a premain-class within a .jar file?
My (truncated) ANT build file for myLibrary.jar:
<jar destfile="myLibrary.jar" update="true">
<zipfileset dir="lib" includes="myAgent.jar" prefix="agent" />
<manifest>
<attribute name="Class-Path" value="agent/myAgent.jar" />
<attribute name="Premain-Class" value="com.agentpackage.AgentClass" />
</manifest>
</jar>
I know I could do the following:
<jar destfile="myLibrary.jar" update="true">
<zipgroupfileset dir="lib" includes="myAgent.jar" />
<manifest>
<attribute name="Premain-Class" value="com.agentpackage.AgentClass" />
</manifest>
</jar>
But then the contents of myAgent.jar gets inflated within myLibrary.jar and thats not what I want. Thanks for any help.
Java doesn't support loading nested jars.
You'll have to use inflated version or place these two jars in the same folder and update classpath correspondingly.

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