Apache Maven tips

Been using Ant & Apache Maven for years, now I seems to be immune with long nested XML and not bother writing about them anymore.

But with this attempt, I hope some tips here will be appreciated by Mrs. Google :-)

.

Bundle all classes of dependent JAR files into our JAR

Given our original POM file is like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>vn.ducquoc.euler</groupId>
  <artifactId>euler</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>ProjectEuler fun</name>
  <description>See http://github.com/ducquoc/euler-fun</description>

  <dependencies>
   <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.7</version>
     <scope>test</scope>
   </dependency>
   <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>1.6.4</version>
   </dependency>
   <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-jdk14</artifactId>
     <version>1.6.4</version>
   </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
          <showWarnings>false</showWarnings>
        </configuration>
        <!--<version>2.3.2</version>-->
      </plugin>
    </plugins>
  </build>
</project>

When Maven build is invoked (like “mvn clean install” ) , it will produce a JAR file, which contains only classes of that project. So when to use it we have to include other dependencies (JAR files) in to the classpath; otherwise it will be either a NoClassDefFoundError or a ClassNotFoundException.

To avoid such trivial time waste, we can include the necessary classes to the newly created JAR. There are several ways to do that, my traditional approach is  to use maven-assembly-plugin :

<build>
  <plugins>
    <!-- to bundle all classes of dependent JAR files -->
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
          <manifest>
            <mainClass>vn.ducquoc.euler.EulerMain</mainClass>
          </manifest>
        </archive>
      </configuration>
      <executions>
        <execution>
          <id>make-assembly</id>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <!-- . . . -->
  </plugins>
</build>

Now the build will output a NAME-jar-with-dependencies.jar file !

.

Bundle necessary classes of dependent JAR files into our JAR

Given our original POM file is like above, my new approach is to use maven-shade-plugin, which is solely designed for this purpose.

<!-- to bundle necessary classes of dependent JAR files -->
 <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-shade-plugin</artifactId>
   <version>1.5</version>
   <executions>
     <execution>
       <phase>package</phase>
       <goals>
         <goal>shade</goal>
       </goals>
       <configuration>
         <transformers>
           <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
             <mainClass>vn.ducquoc.euler.EulerMain</mainClass>
           </transformer>
         </transformers>
         <!--<shadedArtifactAttached>true</shadedArtifactAttached>-->
       </configuration>
     </execution>
   </executions>
 </plugin>

.

That’s it. There are still some other Maven plugins which can serve the purpose (like “onejar”, “jarjar”, … ) , yet shade is enough :-)

 

.

[OffTopic]

For Clojure, leiningen has the built-in uberjar command

$ lein uberjar

[/OffTopic]

 

./.

 

About DucQuoc.wordpress.com

A coder, brother, and player at times...
This entry was posted in Coding. Bookmark the permalink.

5 Responses to Apache Maven tips

  1. [ERROR] Failed to execute goal org.codehaus.enunciate:maven-enunciate-plugin:1.25:assemble (default) on project hudson-rest-api: Execution default of goal org.codehaus.enunciate:maven-enunciate-plugin:1.25:assemble failed: A required class was missing while executing org.codehaus.enunciate:maven-enunciate-plugin:1.25:assemble: com/sun/mirror/apt/AnnotationProcessorFactory

    ==> Work-around for maven-enunciate-plugin issue with Java 7:

    http://jira.codehaus.org/browse/ENUNCIATE-603?focusedCommentId=302322#comment-302322

    hope this helps,

  2. Some tests encounter OutOfMemoryError when using maven-compiler-plugin?

    Solution 1: set environment variable MAVEN_OPTS
    + DOS (Windows): set without using quote
    set MAVEN_OPTS=-Xmx512m -XX:MaxPermSize=384m
    + Bash (Linux): export the env var
    export MAVEN_OPTS=”-Xmx512m -XX:MaxPermSize=128m”

    Solution 2: configure the Compiler plugin and test plugin (surefire/failsafe) :

    org.apache.maven.plugins
    maven-surefire-plugin
    ${maven-surefire-plugin.version}

    once
    -Xmx1024m -XX:MaxPermSize=512m

    maven-compiler-plugin
    ${maven-compiler-plugin.version}

    1.6
    1.6
    1024m
    128m
    true

    (or use the latest stable version of the plugin)

  3. Pingback: Why Maven 3 | DucQuoc's Blog

  4. Some tips to reduce build time with Maven:

    1/ Skip tests: by -DskipTests=true or -Dmaven.test.skip=true

    2/ Comment out unnecessary plugins in POM.xml: For example, with Cirrus build we can comment out the enunciate plugin (just comment out the docs is enough)

    3/ Use maven 3 instead of maven 2. (In general maven 3 build faster 20%-30%)

    4/ Setup the frequently used build command to a script (.bat file), or utilize IDE to remember that with one click

  5. Pingback: Logging best practices | DucQuoc's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s