findResource("") returning null when module-info.java is present, why is that? findResource("") returning null when module-info.java is present, why is that? java java

findResource("") returning null when module-info.java is present, why is that?


One thing I notice is that your application (assuming that it's packaged in tech.flexpoint.dashman) does not seem to be opened up to Spring in any way, which will surely result in failed class loading/illegal access.

I would expect to see something like this in module-info.java (depending on your Spring dependencies):

opens tech.flexpoint.dashman to spring.core, spring.beans, spring.context;

The exception is a NoClassDefFoundError, which is thrown at runtime when the class definition of a class that was known at compile time cannot be resolved, in this case the interface javax.transaction.UserTransaction, which is part of the Java Transaction API (JTA).

As others have pointed out, JTA is not bundled with the JDK, and needs to be added as a compile dependency. However, the class that needs to load the UserTransaction class definition comes from the spring-boot-autoconfigure artifact, which is responsible for its own dependencies (spring-boot-autoconfigure@2.4.0.RELEASE 🡒 jboss-transaction-spi@7.6.0.Final 🡒 jboss-transaction-api_1.2_spec@1.1.1.Final), so you should not need to add JTA as a dependency.

However, because you want to package your own app as a Java 9 module, it needs to explicitly state its dependencies. spring-boot-autoconfigure is not yet a modularized Java 9 library, and does not do this for you (i.e. transitively). The automatic module name for JTA is java.transaction, so you need to add the requirement in module-info.java:

requires java.transaction;

I got your example running and did indeed get NoClassDefFoundErrors when running from IntelliJ IDEA. The stacktrace pointed back to a ClassNotFoundException, which indicates classpath problems. Since IDEA calculates the classpath when launching the application from there, I wanted to see if I could reproduce the error when using the spring-boot-maven-plugin to run the application.

I copied the IDEA run configuration to the spring-boot-maven-plugin configuration, as shown below:

<plugin>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-maven-plugin</artifactId>  <configuration>      <mainClass>tech.flexpoint.demo.DemoApplication</mainClass>      <jvmArguments>--show-module-resolution --add-opens=java.base/java.lang=spring.core --add-opens=java.base/java.io=tomcat.embed.core --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED</jvmArguments>      <workingDirectory>${project.basedir}</workingDirectory>  </configuration></plugin>

Then I invoked mvn spring-boot:run and voila, the application booted successfully without errors.I can only conclude that this is an issue with the classpath calculated by IntelliJ.


Assuming you have declared the dependency:

<dependency>    <groupId>javax.transaction</groupId>    <artifactId>javax.transaction-api</artifactId>    <version>1.3</version></dependency>

Include the following in module-info.java:

requires java.transaction;

Version 1.3 declares the automatic module name, while version 1.2 doesn't.
The latter requires javax.transaction.api;. Source


As you have mentioned in your original problem, the code works without module-info.java but not with the module-info.java. I can see that you have done all this hard work in explaining the problem, creating a minimal project and so on to drill down to the problem.

Looking at your problem it is obvious that one of the modules is causing the URLClassLoader.findResource("") returning null. It might be one of the modules down the list is overriding this class method or have an ambiguous implementation.

Why don't you start with an empty module-info.java for the minimal example and keep adding 1 module at a time till we see the error? I believe this will help us find the culprit.