Solved

using ant to define multiple jars in classpath with manifest tag

Posted on 2006-11-15
33
1,631 Views
Last Modified: 2013-11-23
I have searched high and low and I still cant seem to figure out how to define multiple jar files (or even one for that matter) within the manifest file using ant.

I am trying to determine what is the best choice for deployment, so I want to try to package the dependencies within my jar file, and well as put them in an external directory.

If my dependencies are located in an external directory, I have the following (which doesnt want to work):

<target name="Myjar" depends="dist, compile, filename" description="generate jar" >
      <jar destfile="${dist}/${jar}">                                                                                                          
            <manifest>
            <attribute name="Main-Class" value="${Main_Class}"/>
            <attribute name="Class-Path" value=".;c:/test/comm.jar;c:/test/db4o5.5jar" />
        </manifest>      
    </jar>
  </target>



I have tried tons of combinations, using different slashes, using spaces, or commands instead of colons, nothing seems to work with respect to the Class-Path attribute. The rest is working fine.

thanks in advance.
0
Comment
Question by:gmoniey
  • 10
  • 10
  • 8
  • +1
33 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 17949327
Try

<attribute name="Class-Path" value=". c:/test/comm.jar c:/test/db4o5.5jar" />
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 17949329
*But* afaik, you can't use absolute paths
0
 

Author Comment

by:gmoniey
ID: 17949423
that doesnt work. I tried using spaces already. Why can't i use absolute paths? I know exactly where the jars will be on my deployment machines
0
 
LVL 13

Expert Comment

by:kawas
ID: 17949805
this should do it. you will have to tweak the 'depends', ${lib.dir}.

The following takes all of the jar files found in ${lib.dir} and adds them to the 'Class-Path' part of the manifest.

<target name="jar" depends="your_compile_depends"
  description="Create a jar file">
  <dirname property="build.lib.dir" file="${lib.dir}"/>
  <!-- dirsep may not be portable -->
  <pathconvert pathsep=" " dirsep="/" property="build.manifest.classpath">
    <map from="${build.lib.dir}" to="."/>
    <path>
      <fileset dir="${lib.dir}" excludes="dir/to/exclude/**" includes="*.jar"/>
    </path>
  </pathconvert>       
  <jar destfile="${build.lib}/YourFileNameHere.jar">
    <fileset dir="${build.classes}" includes="package/that/is/included/here/**"/>
    <manifest>
      <attribute name="Built-By" value="${user.name}"/>
      <attribute name="Class-Path" value="${build.manifest.classpath}"/>
      <attribute name="Main-Class" value="your.package.declaration.Main"/>
    </manifest>       
  </jar>
</target>
0
 

Author Comment

by:gmoniey
ID: 17950938
Hi kawas,

I havent tried your solution yet, because I honestly don't understand all of it. I don't see why i have to tweak my 'depends' (is it because I need to ensure that the ${lib.dir} exists? also, is the ${lib.dir} variable a system variable, or one that I define.

Also, is your example packing the depndency jars with the jar I am creating? or are they assumed to be external dependencies (I am actually looking to implement both of these solutions, as I want to determine which is most feasible)

Lastly, I how it isn't too much to ask, but could you break down the "pathconvert" section? That is primarily where I am lost (as from what i gather the lines before that simply assign the ${build.lib.dir} variable to be the file path of the ${lib.dir} variable)

thanks!
0
 
LVL 13

Accepted Solution

by:
kawas earned 43 total points
ID: 17951077
HI,

${lib.dir} is an ant variable, like:    <property name="lib.dir" value="c:/myDir/lib"/>

The solution assumes that the libs are external to the jar

The pathconvert section is mapping jar files from c:/myDir/lib/A.jar to ./lib/A.jar

// puts a space in between jar file locations
<pathconvert pathsep=" " dirsep="/" property="build.manifest.classpath">
// converts all absolute paths to a relative one
    <map from="${build.lib.dir}" to="."/>
    <path>
// for all the jar files in lib.dir, excluding those in dir/to/exclude, convert the file paths
      <fileset dir="${lib.dir}" excludes="dir/to/exclude/**" includes="*.jar"/>
    </path>
  </pathconvert>  

Does this help?
0
 

Author Comment

by:gmoniey
ID: 17951201
Hi kawas,

It didn't work, and I believe I know why. Your solution assumes that my jar file will be in the lib directory. Unfortunately, that is not the case here. The dependencies will be in a shared directory, which i do not want to place the jar file within. (This dependency directory will always be available)

I want to jar file to be portable...i.e. the end user can move it around, and the manifest will point to an absolute path where the dependencies can be found.
0
 

Author Comment

by:gmoniey
ID: 17951374
I figured it out...

if you add a leading slash, and use spaces it works

i.e.

<target name="Myjar" depends="dist, compile, filename" description="generate jar" >
     <jar destfile="${dist}/${jar}">                                                                                                          
          <manifest>
            <attribute name="Main-Class" value="${Main_Class}"/>
            <attribute name="Class-Path" value=". /c:/test/comm.jar /c:/test/db4o5.5jar" />
        </manifest>      
    </jar>
  </target>

After some searching, it seems that it is not possible to pack jars within a jar, and add them to the classpath without using a custom class loader. If anyone has an example of this, or knows of another way, please let me know. thanks!

0
 
LVL 92

Expert Comment

by:objects
ID: 17951402
may be of interest

http://one-jar.sourceforge.net/
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 17951473
>>After some searching, it seems that it is not possible to pack jars within a jar, and add them to the classpath without using a custom class loader. If anyone has an example of this, or knows of another way, please let me know. thanks!

It's perfectly possible with the tool  you've got (Ant)

Just use a zipfileset element and specify your jars
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 41 total points
ID: 17951480
Here's one of mine:

   1 <project name="OggClock" default="build" basedir=".">
   2         <target name="build" description="Build and merge-jar OggClock (a command line speaking clock)">
   3                 <property name="extra-jars" value="${user.home}/java-libraries"/>
   4
   5                 <jar destfile="oggclock.jar" compress="true">
   6                         <manifest>
   7                                 <attribute name="Main-Class" value="net.proteanit.util.time.OggClock"/>
   8                         </manifest>
   9
  10                         <fileset dir="bin" includes="net/proteanit/util/time/*.class"/>
  11                         <fileset dir="." includes="oggfiles/*.ogg"/>
  12                         <!-- Put the source in as well -->
  13                         <fileset dir="bin" includes="net/proteanit/util/time/*.java"/>
  14                         <zipfileset src="${extra-jars}/jogg-0.0.7.jar" includes="**"></zipfileset>
  15                         <zipfileset src="${extra-jars}/jorbis-0.0.15.jar" includes="**"></zipfileset>
  16                         <zipfileset src="${extra-jars}/tritonus_share.jar" includes="**"></zipfileset>
  17                         <zipfileset src="${extra-jars}/vorbisspi1.0.2.jar" includes="**"></zipfileset>
  18                 </jar>
  19         </target>
  20
  21 </project>
0
 

Author Comment

by:gmoniey
ID: 17951598
Could you explain exactly what that fileset is doing? i am tryin to implement it with my code, but i dont see how is establishes the classpath?

Also, do you happen to know how to embed quotes within an ant variable?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 17951622
You don't need a classpath as all the classes are in the correct root-relative path

>>Also, do you happen to know how to embed quotes within an ant variable?

Can you show where you need that?

0
 
LVL 92

Expert Comment

by:objects
ID: 17951654
it doesn't incoude the jars, it incudes the classes.
more manageable to keep the jars intact imo
0
 

Author Comment

by:gmoniey
ID: 17951665
I suppose that works. personally i would rather keep the jars in jar form, but i suppose i dont have much of a choice

as for the example of using quotes within a variable.

I cant reference the directory: C:\Program Files because of the space. I can refer to it as C:\Progra~1, but I wanted to know if it would be possible to insert quotes
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 92

Expert Comment

by:objects
ID: 17951708
> personally i would rather keep the jars in jar form

i agree

>  but i suppose i dont have much of a choice

u do :)

why don't u distribute all the jars in the one directory to keep it simple?
0
 
LVL 92

Expert Comment

by:objects
ID: 17951716
>Also, do you happen to know how to embed quotes within an ant variable?

have tried escaping them?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 17951724
>>I cant reference the directory: C:\Program Files because of the space.

That should be OK as an Ant attribute. Forward slashes can be used too
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 17951736
You might try

x="&quot;C:/Program Files/X/Y/Z&quot;"
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 17951770
>>why don't u distribute all the jars in the one directory to keep it simple?

How?
0
 

Author Comment

by:gmoniey
ID: 17951778
well, the &quot; worked, as far as adding the " character, but it didn't resolve the classpath. It seems that i will just have to stick with c:\progra~1 for now.

As for referencing jar files within a jar, I think i would rather use a custom classloader and keep the jars intact. and organized within a lib directory.
0
 
LVL 92

Expert Comment

by:objects
ID: 17951821
why do your dependant jars need to be in a seperate directory to the application jar, keeping them in the same directory would get rid of your problem.
0
 

Author Comment

by:gmoniey
ID: 17951843
I want to keep the dependent jars in a different directory because I want to jar file to be portable...i.e. drag it to any folder, and it will still work.
0
 
LVL 92

Assisted Solution

by:objects
objects earned 41 total points
ID: 17951882
unfortunately executable jars aren't designed to work like that.

why not put the dependant jars in <jre>/lib/ext, that way you won't need to specify them at all.

Why do you need the application jar to be able to be moved around. You could create a bat script to start your app, allowing that instead to be moved around if nneded.
0
 

Author Comment

by:gmoniey
ID: 17951988
The whole reason I am doing this is to remove jars from <jre>/lib/ext. Personally, I think it is bad design to include 3rd party jars in that folder, but that is subject to a whole different argument.

My primary reason for removing jars from the ext directory is that you cant have two versions of the same jar file (i.e. and old version, and a new version). Furthermore, java may use a different class loader for the ext jars, than what is used for your application, resulting in some classes not being loaded.

Why should i create a bat script? its just more work. Maybe a windows shortcut if i wanted to add an icon and such, but for development purposes, i want to be able to move a jar around to whatever machine i wish (provided that machine is setup with the jars i require...which they are)...and run the jar...no creating bat files, and changing the name to match my newly created jars...just point and click
0
 
LVL 92

Expert Comment

by:objects
ID: 17952034
executable jars don't really support that sort of thing.
another option would be to use web start, that way user wouldn't need to worry about jars at all (which you probably don't want them doing anyway).
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 17953884
>>i want to be able to move a jar around to whatever machine i wish

You can only do that when you have one jar
0
 

Author Comment

by:gmoniey
ID: 17953909
From what I have read, it should be possible using a custom classloader...not exactly the solution i want, but i am gonna give it a try
0
 
LVL 92

Expert Comment

by:objects
ID: 17953910
> You can only do that when you have one jar

already been mentioned, no need to always repeat previous comments.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 17953923
>>From what I have read, it should be possible using a custom classloader.

Yes - that's how 'OneJar' works, but you still have one jar. How many jars do you want?
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now