views:

645

answers:

2

Hi,

I have a maven project and I'd like to create a distribution of it with the dependencies. I've tried the maven-assembly-plugin and built the jar with dependencies, but that unpacked all of the jars and repackaged them all into a big, single jar. What I'd like is something like my jar file and a lib folder that has all of the dependencies. Then when I run it, I could run "java -cp lib/* my.package.MainClass".

What's the best way to go about doing this with maven? Or the recommended way to deploy?

thanks,

Jeff

+1  A: 

See:

http://maven.apache.org/shared/maven-archiver/index.html

You should be able to use the maven-jar plugin to package up an archive, specify the main class to execute along with the classpath. It can generate a manifest file for you for your project.

http://maven.apache.org/shared/maven-archiver/examples/classpath.html#Prefix

Jon
Jon, thanks. I was able to properly generate the manifest, but is there a way to actually then create the directory structure I need? for example, I made the classpathPrefix lib/ and I would like to have a lib directory generated with the dependencies copied to it.
Jeff Storey
The second link here tells you how to do this... http://maven.apache.org/shared/maven-archiver/examples/classpath.html#Prefix
Jon
+2  A: 

I have used the Maven assembly just for that in my project.

First enable your plugin in your POM and call your assembly config :

  <plugin>
   <artifactId>maven-assembly-plugin</artifactId>
   <!--I recommend 2.1 as later versions have a  bug that may
                                Duplicate files in your archive
                            -->
                            <version>2.1</version>
   <!--Executes the packaging along with the mvn package phase
                            -->
   <executions>
    <execution>
     <id>make-assembly</id>
     <phase>package</phase>
     <goals>
      <goal>attached</goal>
     </goals>
    </execution>
   </executions>
   <configuration>
    <descriptors>
           <!--Relative path to your descriptor -->
     <descriptor>src/main/assembly/package.xml
            </descriptor>
    </descriptors>
   </configuration>
  </plugin>

Then in your descriptor you can decide how you want your layout to be before you package the whole thing

<assembly>
    <!-- this will create an extra resource project-1.1.1-package.zip, you can
         choose jar as well in the format-->
    <id>package</id>
    <formats>
     <format>zip</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <!-- Insert here extra files as configs or, batch files, resources, docs etc-->
    <fileSets>
     <fileSet>
      <directory>src/main/assembly/files</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
       <include>**/conf/*.*</include>
       <include>**/doc/*.*</include>
      </includes>
     </fileSet>
            <!-- I like to integrate the jre as well... simplifies my deployement -->
     <fileSet>
      <directory>target/jre</directory>
      <outputDirectory>/jre</outputDirectory> 
     </fileSet>
    </fileSets>
    <!-- This will scrub your dependencies and add them to your lib folder, I excluded
         Test stuff as it is not needed, could have declared the resource as a test
         only phase as well would not have had to exclude it here
    -->
    <dependencySets>
     <dependencySet>
      <outputDirectory>lib</outputDirectory>   
      <excludes>
       <exclude>junit:junit</exclude>
      </excludes>
     </dependencySet>
    </dependencySets>
</assembly>

This will create a zip file with the layout you have specified in your output directory config, package the whole thing as a zip file (you can choose zip, jar, war ...) and deploy it in my repository with the rest.

I skipped bits and pieces to make it simpler but my package expands to include batch files, dlls, config, doc and the JRE so everything needed is in the same zip... all is needed to run the thing is extract and click start.bat !

I could also probably make it in to a jar properly formatted with METADATA and just double click the jar itself to start it all, I did not need or have time to toy around this option but you may try it as well.

Beware of versions above 2.1 of the assembly plugin, it will create duplicate entries if your directives enable it to find the same file in different locations, this will give you a lib folder with the same jars repeating twice. not very dangerous as unzipping will collapse them but still annoying to have the unzip ask you if you want to overwrite files. Plus the fact that you do not know which won if somehow they turned out to be different in content.

Maven is great but I find that it is sometimes frustrating to get it working, Plus documentation can sometimes be hard to find and use. However, used appropriately it will save you tons of time.

good luck

Newtopian
awesome, thanks for the detailed answer. I'm going to give this a try.
Jeff Storey
give me a buzz if you have problems with this approach.. there may be other ways to achieve similar results but this one works well for me.
Newtopian
so far so good. i gave it a try, but a couple of other quick questions.my actual snapshot file ended up the lib directory too. i was hoping to have that outside the lib dir - is that possible?also, can i use this in conjunction with the maven-jar-plugin to generate a manifest file and make this an executable jar? or would I be better off just creating a script that launches the app and including that?thanks again!
Jeff Storey
you could have a fileset that excludes your jar from the lib and place it in the root of your zip file. add an exclude clause in the dependency set and create a new fileset that looks into your target/ folder for your jar. I personally liked the script approach as I could adjust the environment prior to launch, but I was running a service so it made more sens for me to use a script.
Newtopian