[GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

Discussion in 'Archives' started by uncle 0wnz, Nov 30, 2008.

[GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]
  1. Unread #1 - Nov 30, 2008 at 12:20 AM
  2. uncle 0wnz
    Joined:
    Nov 19, 2008
    Posts:
    108
    Referrals:
    0
    Sythe Gold:
    0

    uncle 0wnz Active Member

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

    JAVA JAR FILES

    What my distribution looked like
    The approach I ended up with was to deliver my application as one jar file, and then include all my dependencies (the other jar files) in the same directory with my jar file. So, if my application was delivered as my-application.jar, I provided it, my distribution directory ended up looking a little like this:

    my-application.jar
    commons-collections.jar
    commons-dbcp-1.1.jar
    commons-pool-1.1.jar
    log4j-1.2.8.jar
    mysql-connector-java-3.1.12-bin.jar

    By creating a custom manifest file and including that manifest file in my jar file, users could then start my application by simply typing:

    java -jar my-application.jar

    at the command line. This is exactly what I wanted to achieve.

    How I built the application
    I've seen approaches where developers hard-code a classpath in their ant build script, and then include that classpath in a manifest file in their jar file. Including the classpath in the manifest file is the right approach to this problem, but hard-coding the classpath is not. As you can imagine, a hard-coded approach is fragile, and will break any time you forget to add a new jar file dependency to the list. (And unfortunately you won't know it's broken until you try to run your application, and hit the part of the application where the dependency is missing.)

    A much better approach is to build the classpath dynamically. I built my application using ant, and built my classpath dynamically using a task named pathconvert, and a mapper named flattenmapper. The following segment of my build.xml file shows the commands that I used:

    <!-- convert classpath to flat list for use in manifest task -->
    <pathconvert property="mf.classpath" pathsep=" ">
    <path refid="build.class.path" />
    <flattenmapper />
    </pathconvert>

    This code says "Create a new property named mf.classpath from the property build.class.path, and when you build mf.classpath, take that build.class.path (which is essentially a list) and flatten it into a space-separated list of files that represents my build class path." This command effectively turns this list:

    commons-collections.jar
    commons-dbcp-1.1.jar
    commons-pool-1.1.jar
    log4j-1.2.8.jar
    mysql-connector-java-3.1.12-bin.jar

    into a string that looks like this:

    commons-collections.jar commons-dbcp-1.1.jar commons-pool-1.1.jar log4j-1.2.8.jar mysql-connector-java-3.1.12-bin.jar

    This string then becomes the classpath entry when you create your manifest file.

    Building the manifest file
    The second part of the solution is properly building the manifest file for your jar file. To create my manifest file I developed a portion of my build.xml file that looks like this:

    <tstamp/><!-- needed for TODAY -->
    <manifest file="MANIFEST.MF">
    <attribute name="Built-By" value="${manifest.built.by}"/>
    <attribute name="Created-By" value="${manifest.created.by}"/>
    <attribute name="Main-Class" value="${manifest.main.class}"/>
    <attribute name="Implementation-Version" value="${version.number}-b${build.number}"/>
    <attribute name="Built-Date" value="${TODAY}"/>
    <attribute name="Class-Path" value="${mf.classpath}" />
    </manifest>

    If you read the specification on manifest files you'll see that a lot of those lines are boilerplate, but the last attribute that looks like this:

    <attribute name="Class-Path" value="${mf.classpath}" />

    is the one that tells my jar file to use the space-separated list of jar files as its classpath when it runs.

    The beauty of this approach is (a) I build my classpath dynamically, based on the jar files I've included in my build path (which is essentially my lib directory), (b) I use that dynamically-created classpath in my manifest file, and (c) I also copy all the necessary jar files to my deployment directory, so the entire process of building a distribution of my application (including all dependencies) is automated.


    The build.xml file
    To wrap this up, here's the entire package target from my ant build script, along with an earlier part of the build script where I create my initial classpath. To keep this build script flexible I do use a large number of variables that I defined earlier in my ant build script, but hopefully those variables won't obscure what I'm trying to show in this article, which is how to dynamically create a classpath you can use to create a distributable, executable jar file.

    With that being said, here are a few snippets of code from my ant build script.

    <!-- First, I create my classpath from all the jar files in my lib directory -->
    <path id="build.classpath">
    <fileset dir="lib">
    <include name="**/*.jar" />
    </fileset>
    </path>

    <!-- Next, my package task uses that classpath -->
    <target name="package" depends="compile">
    <echo>=== PACKAGE ===</echo>

    <!-- convert classpath to flat list for use in manifest task -->
    <pathconvert property="mf.classpath" pathsep=" ">
    <path refid="build.classpath" />
    <flattenmapper />
    </pathconvert>

    <tstamp/><!-- needed for TODAY -->
    <manifest file="MANIFEST.MF">
    <attribute name="Built-By" value="${manifest.built.by}"/>
    <attribute name="Created-By" value="${manifest.created.by}"/>
    <attribute name="Main-Class" value="${manifest.main.class}"/>
    <attribute name="Implementation-Version" value="${version.number}-b${build.number}"/>
    <attribute name="Built-Date" value="${TODAY}"/>
    <attribute name="Class-Path" value="${mf.classpath}" />
    </manifest>

    <jar basedir="${dest.dir.classes}"
    destfile="${package.file}"
    includes="**/*.*"
    excludes="**/*Test*"
    manifest="MANIFEST.MF" />

    <copy todir="${dest.dir}">
    <fileset dir="${lib.dir}">
    <exclude name="${lib.cobertura.dir}" />
    <exclude name="junit*" />
    <include name="*.jar"/>
    <include name="*.zip"/>
    </fileset>
    </copy>
    <!-- move this file before the 'jar' task (and put it in the 'classes' dir) if you want to
    include it in the jar -->
    <copy file="${resources.dir}/log4j.properties" tofile="${dest.dir}/log4j.properties" overwrite="true" />
    <copy file="${resources.dir}/${properties.file}" tofile="${dest.dir}/${properties.file}" overwrite="true" />
    <delete dir="${dest.dir.classes}" />
    </target>
     
  3. Unread #2 - Nov 30, 2008 at 12:28 AM
  4. MatthewGor123
    Joined:
    Dec 17, 2005
    Posts:
    1,213
    Referrals:
    0
    Sythe Gold:
    0

    MatthewGor123 Guru
    Do Not Trade

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

  5. Unread #3 - Nov 30, 2008 at 12:29 AM
  6. uncle 0wnz
    Joined:
    Nov 19, 2008
    Posts:
    108
    Referrals:
    0
    Sythe Gold:
    0

    uncle 0wnz Active Member

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

  7. Unread #4 - Nov 30, 2008 at 12:59 AM
  8. Rawr
    Joined:
    Jul 18, 2008
    Posts:
    2,442
    Referrals:
    10
    Sythe Gold:
    13
    Pokémon Trainer

    Rawr Addict.
    Retired Sectional Moderator $100 USD Donor

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

  9. Unread #5 - Nov 30, 2008 at 1:00 AM
  10. uncle ownz
    Referrals:
    0

    uncle ownz Guest

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

    i did,and no where in my post does it say i made it,learn to read the rules stupid child.
     
  11. Unread #6 - Nov 30, 2008 at 1:07 AM
  12. Rawr
    Joined:
    Jul 18, 2008
    Posts:
    2,442
    Referrals:
    10
    Sythe Gold:
    13
    Pokémon Trainer

    Rawr Addict.
    Retired Sectional Moderator $100 USD Donor

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

    If you're going to rip, at least do it properly.
     
  13. Unread #7 - Nov 30, 2008 at 1:09 AM
  14. uncle ownz
    Referrals:
    0

    uncle ownz Guest

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

    No Plagiarism - Plagiarism is copying another person's work and passing them off as your own...hey why dont you read that part once...has it set in yet?
     
  15. Unread #8 - Nov 30, 2008 at 1:10 AM
  16. uncle ownz
    Referrals:
    0

    uncle ownz Guest

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

    again-i never said it was my guide.GF?
     
  17. Unread #9 - Nov 30, 2008 at 1:13 AM
  18. Rawr
    Joined:
    Jul 18, 2008
    Posts:
    2,442
    Referrals:
    10
    Sythe Gold:
    13
    Pokémon Trainer

    Rawr Addict.
    Retired Sectional Moderator $100 USD Donor

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

    Still, if you would have abide the rules, you're other account wouldn't have gotten banned. GF, I'm done now.
     
  19. Unread #10 - Nov 30, 2008 at 1:13 AM
  20. MatthewGor123
    Joined:
    Dec 17, 2005
    Posts:
    1,213
    Referrals:
    0
    Sythe Gold:
    0

    MatthewGor123 Guru
    Do Not Trade

    [GUIDE]Create an executable jar file by dynamically referencing the jar files[GUIDE]

    Use the dispute forum if you want to dispute a ban. I know the rules; I spend more time in UE than the vast majority of Sythe users. Trust me, I know them. You:
    1) Failed to cite your source.
    2) Passed it off as your own; "I" attempted to do this, "I" made this, etc. You obviously have no knowledge on this sbject.
     
< Need p2p pvp parthner for 76k kills | Need f2p junking partner >

Users viewing this thread
1 guest


 
 
Adblock breaks this site