Search code examples
javamavendependenciesmulti-modulemaven-module

Unable to use submodule dependency class in test, throws NoClassDefFoundError


I am working on a maven multi-module project with the following structure

project/
├── migration/
│   ├── src/
│   │   ├── main/
│   │   │   └── Migration.java
│   │   └── test
│   └── pom.xml
├── depends-on-migration/
│   ├── src/
│   │   ├── main (uses Migration.java - ok)
│   │   └── test (uses Migration.java - throws NoClassDefFoundError)
│   └── pom.xml (depends on migration)
└── pom.xml

The class can be used (see image), but cannot compile when I run mvnw package (see logs)

enter image description here

2022-12-17T14:22:56.025+08:00  INFO 13468 --- [           main] c.b.d.DependsOnMigrationApplicationTests : Starting DependsOnMigrationApplicationTests using Java 17.0.2 with PID 13468 (started by Joseph in Z:\bwgjoseph\maven-nested-multi-module-project\depends-on-migration)
2022-12-17T14:22:56.031+08:00  INFO 13468 --- [           main] c.b.d.DependsOnMigrationApplicationTests : No active profile set, falling back to 1 default profile: "default"
2022-12-17T14:22:57.289+08:00  INFO 13468 --- [           main] c.b.d.DependsOnMigrationApplicationTests : Started DependsOnMigrationApplicationTests in 1.534 seconds (process running for 2.498)
[ERROR] Tests run: 2, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.493 s <<< FAILURE! - in com.bwgjoseph.dependsonmigration.DependsOnMigrationApplicationTests
[ERROR] test1  Time elapsed: 0.454 s  <<< ERROR!
java.lang.NoClassDefFoundError: com/bwgjoseph/migration/Migration
        at com.bwgjoseph.dependsonmigration.DependsOnMigrationApplicationTests.test1(DependsOnMigrationApplicationTests.java:17)
Caused by: java.lang.ClassNotFoundException: com.bwgjoseph.migration.Migration
        at com.bwgjoseph.dependsonmigration.DependsOnMigrationApplicationTests.test1(DependsOnMigrationApplicationTests.java:17)

[INFO] 
[INFO] Results:
[INFO]
[ERROR] Errors: 
[ERROR]   DependsOnMigrationApplicationTests.test1:17 NoClassDefFound com/bwgjoseph/migr...
[INFO]
[ERROR] Tests run: 2, Failures: 0, Errors: 1, Skipped: 0

This is a simplified example, can refer to repo (migration and depends-on-migration module)

I couldn't find anything similar, the closest I could find are cases where they are looking to use classes that are defined in migration/src/test but I am using migration/src/main

Glad to provide more information if required.

Thanks!


Solution

  • The problem stems from the fact that you use spring-boot-maven-plugin in both migration and depends-on-migration modules.

    Spring Boot Maven Plugin produces an Uber-Jar, with a layout expected by Spring apps. The original jar (without dependencies) is renamed to migration-0.0.1-SNAPSHOT.jar.original

    The structure of uber-jar

    .
    ├── BOOT-INF
    │   ├── classes
    │   ├── classpath.idx
    │   ├── layers.idx
    │   └── lib
    ├── META-INF
    ├── migration-0.0.1-SNAPSHOT.zip
    └── org
        └── springframework
    

    Your code is placed in BOOT-INF/classes - this is not a typical library layout, hence ClassNotFoundException.

    See The Executable Jar Format for reference.

    If you remove spring-boot-maven-plugin in migration project, mvn package passes.