1

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>

<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>first.second</groupId>
    <artifactId>mytestapp</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>mytestapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
               
               <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>first.second.MyTest</mainClass>
            </manifest>
        </archive>
    </configuration>
    <executions>
        <execution>
            <id>assemble-all</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>
               
        </plugins>
        
    </build>
</project>

mytestapp-0.0.1-SNAPSHOT-jar-with-dependencies.jar:

enter image description here

So the final jar with dependencies doesn't include junit dependency.

Therefore when I try to run MyTest:

java -cp mytestapp-0.0.1-SNAPSHOT-jar-with-dependencies.jar first.second.MyTest

I get

MyTest main
Exception in thread "main" java.lang.NoClassDefFoundError: org/junit/Assert
        at first.second.MyTest.main(MyTest.java:16)

output and exception

MyTest.java:

package first.second;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class MyTest 
{
    public static void main( String[] args )
    {
        System.out.println("MyTest main");
        assertEquals(1, 1);
    }
}

How do I make maven assembly plugin include junit jar inside the jar with dependencies, so that

java -cp mytestapp-0.0.1-SNAPSHOT-jar-with-dependencies.jar first.second.MyTest

runs without errors?

I'm aware there are other questions on this topic, but having tried many of the suggested answers, the dependency jars are still not included.

parsecer
  • 4,758
  • 13
  • 71
  • 140

2 Answers2

1

Tell Maven to download your dependencies by using the dependency plugin like so:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.1.2</version>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>

After that you have the jars in the target/lib directory. Now you can add this directory to your assembly.

Queeg
  • 7,748
  • 1
  • 16
  • 42
  • 1
    Thank you, but I wanted to understand why the assembly plugin wouldn't do it. But I'm sure your answer will help future readers! – parsecer May 05 '23 at 23:50
  • 1
    TBH I missed what the others noted: The different classpaths used for compilation, testing and at runtime. I think it is sufficiently well explained meanwhile, thanks for the upvote anyway. :-) – Queeg May 06 '23 at 19:21
1

Normally is a typical "test" dependency, but it doesn't have to be...

To make it "available" for "main" classes:

  • at compilation - we have to remove (because it is the default) or set <scope>compile</scope>
  • at runtime - we set <scope>runtime</scope>

These will also receive more consideration by jar-with-dependencies (assembly-plugin built-in descriptor).

More details: introduction-to-dependency-mechanism

The generated jar with dependencies now looks like this inside:

enter image description here

parsecer
  • 4,758
  • 13
  • 71
  • 140
xerx593
  • 12,237
  • 5
  • 33
  • 64
  • What if it were not a JUnit but any other random library, for instance, JSoup? https://mvnrepository.com/artifact/org.jsoup/jsoup Would the `runtime` scope not be obligatory? Update: tried to import `JSoup` and use it, it's included in the `jar` without any scope specified (the jar runs fine!) – parsecer May 05 '23 at 23:53
  • So any dependency that has scope `test` or scope `compile` won't be added as a `jar` inside the fat `jar`? So it's not a `JUnit` specific issue, right? – parsecer May 05 '23 at 23:54
  • Update: I tried to simply remove `test` from the `junit` dependency in the original project (the subject of this post) and the `junit` jars gets included in the jar with dependencies! So it looks like, including the `runtime` is not necessary! Or are there any benefits to doing that? – parsecer May 05 '23 at 23:57
  • 1
    1. No scope == compile scope (default). 2. When I don't need something for compilation (but only at runtime), i would prefer runtime-scope ..the details/diffs are in the according (compile/runtime;) plugins and (transitive) dependency resolution..for details consult the [link]/according plugin documentation..and (3.) With above said regarding "jar-with-dependencies considers dependencies with scope>=runtime" ..and your tests/xp..it means: "compile >= runtime" – xerx593 May 06 '23 at 02:25