Pages

Jar with dependencies through Maven

I'm creating a Java desktop app, a very simple one, see the previous post if you don't believe me, using Maven as build manager. The second step here is adding a dependency, and let Maven build a "fat" jar including them, to ease its deployment.

Say that I just want to use Logback classic in my application. I search for it on MvnRepository, I stay away from the alpha version so I go for 1.2.3.

Given that, modify my pom.xml is mostly a matter of copy and paste. Just remember that any dependency belongs to the dependencies element.
<project ...>
    <!-- ... -->
    <dependencies>
     <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
     </dependency>
    </dependencies>
</project>
Now I can Logback, and I'm going to do it through SLF4J.
import org.slf4j.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger LOG = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        // ...
        LOG.info("Hello");
    }
}
I run my application in Eclipse, everything goes as expected, getting as console output the required log
14:32:12.986 [main] INFO simple.Main - Hello
Now I run a maven build, as done in the previous post, setting the goals to clean package, and generate a jar.

I run it from the shell in the usual way
java -cp simple-0.0.1-SNAPSHOT.jar simple.Main
And I get a nasty feedback
Exception in thread "main" java.lang.NoClassDefFoundError:
    org/slf4j/LoggerFactory at simple.Main.(Main.java:7)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
    at java.base/jdk.internal.loader....
    ...
    ... 1 more
However, this is an expected behavior. Maven generates by default a "slim" jar, avoiding to include in it the dependencies. The user has to specify in the classpath where Java has to find them.

When we want to create a "fat" jar, we should say to Maven explicitly to do it. We do that with the Maven Assembly Plugin.

Maven, please, when you build this project, use the maven-assembly-plugin, version 3.3, when packaging. And, remember to build also a "fat" jar with all the dependencies!
<build>
 <plugins>
  <plugin>
   <artifactId>maven-assembly-plugin</artifactId>
   <version>3.3.0</version>
   <executions>
    <execution>
     <phase>
      package
     </phase>
     <goals>
      <goal>single</goal>
     </goals>
    </execution>
   </executions>
   <configuration>
    <descriptorRefs>
     <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
   </configuration>
  </plugin>
 </plugins>
</build>
Now, when I run the Maven build step, I get both slim and fat jar, here is how I run the latter
java -cp simple-0.0.1-SNAPSHOT-jar-with-dependencies.jar simple.Main
It works fine, so I push the changes on github.

No comments:

Post a Comment