• Home
  • RSS Feed
  • Log in


Maven appassembler Plugin: Dealing with Long Classpaths on Windows
Posted by ShriKant Vashishtha in the early afternoon: November 22nd, 2009

When it comes to generating command-line scripts for Java applications, Maven “appassembler” plugin comes handy. Its “assemble” goal does all the maven magic, i.e. searching the dependencies used for creating the Java application, adding them into the classpath of resultant script and finally copying all relevant jars to a single place. It was all working very nicely until I stumbled across the problem of long classpaths in the Windows OS.

Irrespective of whether you use DOS prompt or cygwin, Windows limits the length of environment variables. Though there are various options to overcome this problem using Java 6 wildcard classpath, mapping the path to some drive etc, they all look like workarounds to me as problem can recur again anytime.

After some amount of research, I found appassembler plugin resolves this issue with booter-windows and booter-unix daemons. From the outset it looked like daemon does something else as the name is a bit misleading but in reality it’s a generic way to start your Java applications. The booter-unix/booter-windows platforms were introduced for the sole purpose of resolving the long classpath issue (see MAPPASM-43) in appassembler maven plugin. Here’s how it looks like in the pom you are working with:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>appassembler-maven-plugin</artifactId>
    <configuration>
        <repositoryLayout>flat</repositoryLayout>
        <installArtifacts>false</installArtifacts>
        <target>${project.build.directory}/appassembler</target>
        <defaultJvmSettings>
            <initialMemorySize>512M</initialMemorySize>
            <maxMemorySize>1024M</maxMemorySize>
            <extraArguments>
                <extraArgument>-DconfigFile=../../etc/config.properties</extraArgument>
                <extraArgument>-Dlog4j.configuration=../../etc/log4j.properties</extraArgument>
            </extraArguments>
        </defaultJvmSettings>
        <configurationDirectory>etc</configurationDirectory>
        <daemons>
            <daemon>
                <id>applicationName</id>
                <mainClass>com.xebia.appassebler.sample.Main</mainClass>
                <platforms>
                    <platform>booter-unix</platform>
                    <platform>booter-windows</platform>
                </platforms>
                <environmentSetupFileName>app-env</environmentSetupFileName>
            </daemon>
        </daemons>
    </configuration>
    <executions>
        <execution>
            < phase>package</phase>
            <goals>
                 <goal>generate-daemons</goal>
                 <goal>create-repository</goal>
            </goals>
        </execution>
    </executions>
</plugin>

If you look at the code carefully, you’ll find “app-env” as a parameter to “environmentSetupFileName” tag. It is quite useful in passing environment variables to the resultant script. Using app-env (for UNIX) and app-env.bat (for Windows) environment setup files, I could pass a modified $REPO environment variable so that the copied repository containing dependencies is shared between booter-unix and booter-windows folders as follows:

|-- booter-unix

|   |-- bin

|   |   |-- applicationName
|   |   `-- app-env

|   `-- etc

|       `-- applicationName.xml

|-- booter-windows

|   |-- bin

|   |   |-- app-env.bat

|   |   `-- applicationName.bat

|   `-- etc

|       `-- applicationName.xml

|-- etc

|   |-- config.properties

|   `-- log4j.properties

`-- repo

    |-- <dependency1>.jar

    |-- <dependency2>.jar

    |-- ...

To copy the environment files and result of appassembler:generate-daemons maven goal to the appropriate locations we can use “maven-assembly-plugin” as follows:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptor>src/main/conf/descriptor.xml</descriptor>
    </configuration>
    <executions>
       <execution>
          <goals>
              <goal>single</goal>
          </goals>
          <phase>package</phase>
       </execution>
    </executions>
</plugin>

Here’s what src/main/conf/assembly.xml looks like:

<assembly>
    <id>bin</id>
    <formats>
        <format>tar.gz</format>
        <format>zip</format>
        <format>dir</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>target/appassembler/booter-unix</directory>
            <outputDirectory>/booter-unix</outputDirectory>
            <excludes>
                <exclude>*.bat</exclude>
                <exclude>*.cmd</exclude>
            </excludes>
            <lineEnding>unix</lineEnding>
            <fileMode>0744</fileMode>
        </fileSet>
        <fileSet>
            <directory>target/appassembler/booter-windows</directory>
            <outputDirectory>/booter-windows</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>target/appassembler/repo</directory>
            <outputDirectory>/repo</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>src/main/conf</directory>
            <includes>
                <include>app-env.bat</include>
            </includes>
            <outputDirectory>/booter-windows/bin</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>src/main/conf</directory>
            <includes>
                <include>app-env</include>
            </includes>
            <outputDirectory>/booter-unix/bin</outputDirectory>
            <lineEnding>unix</lineEnding>
        </fileSet>
    </fileSets>
</assembly>

Now, if you run “mvn clean package”, it provides you the structure as mentioned in listing 2. You can execute the script from booter-windows/bin/applicationName.bat on Windows without worrying about long classpaths now.

Share

Tags: long classpath on windows, Maven, maven appassembler, maven appassembler booter
Filed under Java | 3 Comments »



3 Responses to “Maven appassembler Plugin: Dealing with Long Classpaths on Windows”



    jonas Says:
    Posted at: November 22, 2009 at 2:47 pm

    What about just using the assembly plugin with the the jar-with-dependencies output descriptor which will explode all dependencies for you inside the assembled jar? What’s the point of having externalized dependencies in separate .jar files? If you need to keep configuration files external just add the “etc” directory to the class path, e.g. java -cp ./etc:myproject-jar-with-dependecies.jar com.MainClass

    Reply


    ShriKant Vashishtha Says:
    Posted at: November 23, 2009 at 5:16 pm

    assembly plugin can be another way to get away with the long classpath issue. However many people may not want to explode all dependencies in one single jar because of several reasons. The solution mentioned works for them.

    Reply


    Alexander Says:
    Posted at: December 21, 2009 at 1:46 pm

    Looks like you reinvented the wheel

    Reply


Leave a Reply

Click here to cancel reply.


Xebia Sites

  • Xebia Corporate
  • Xebia France
  • Xebia India
  • XebiCon 2012

Categories

  • Java (312)
  • Agile (192)
  • General (141)
  • Scrum (70)
  • Testing (65)
  • Architecture (65)
  • Performance (47)
  • Middleware (59)
    • Deployment (40)
  • Xebia Labs (41)
  • SOA (31)
  • Project Management (31)
  • Podcast (31)
  • Tools (28)
  • Uncategorized (24)
  • lean architecture (20)
  • Quality Assurance (19)
  • Articles (15)
  • Requirements Management (14)
  • Virtualization (21)

Tag Cloud

    ACT Eclipse JPA implementation patterns Xebia Scala Agile Flex Scrum Moving to India Hibernate Maven TDD Ajax XML product owner Oracle Architecture Groovy Concurrency Control Javascript lean architecture Frameworks agile architectuur SOA Java lean architectuur Grails JPA Spring Lean

Archives

  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
Avatars by Sterling Adventures