findResource("") returning null when module-info.java is present, why is that?
Solution 1:
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 ([email protected]
🡒 [email protected]
🡒 [email protected]
), 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 NoClassDefFoundError
s 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.
Solution 2:
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