I have a JavaFX project and I use Maven for dependency management. Everything is working fine, until I add maven dependency for "mariadb-java-client" in order to get MariaDB JDBC Driver. Then I get "java.lang.NoClassDefFoundError: org.slf4j.Logger" error.
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.3.3</version>
</dependency>
I'm getting the following error:
Exception in Application init method
Exception in thread "main" java.lang.RuntimeException: Exception in Application init method
at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:888)
at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:857)
Caused by: java.lang.NoClassDefFoundError: org.slf4j.Logger
at org.apache.logging.slf4j.SLF4JLoggerContext.getLogger(SLF4JLoggerContext.java:36)
at org.apache.commons.logging.LogAdapter$Log4jLog.<init>(LogAdapter.java:159)
at org.apache.commons.logging.LogAdapter$Log4jAdapter.createLog(LogAdapter.java:113)
at org.apache.commons.logging.LogAdapter.createLog(LogAdapter.java:95)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:67)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:59)
at spring.boot@3.2.2/org.springframework.boot.SpringApplication.<clinit>(SpringApplication.java:202)
at com.mypackage/com.mypackage.CustomerApp.init(CustomerApp.java:72)
at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:817)
... 2 more
Caused by: java.lang.ClassNotFoundException: org.slf4j.Logger
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:827)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1095)
... 11 more
The error is thrown at the startup of the application. The only code line to my code from Stack trace point to line 72 in CustomerApp.java which the following piece of code at the initilization stage of the app where I set the Spring Context:
@Override
public void init() throws Exception {
springContext = SpringApplication.run(CustomerApp.class);
}
I tried everything I have found in previous questions. I have tried to adding "slf4j-api" , "slf4j-log4j12", "slf4j-simple" etc.
Nothing helped.
My dependencies in pom.xml:
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
<classifier>${javafx.classifier}</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
<classifier>${javafx.classifier}</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
<classifier>${javafx.classifier}</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>${javafx.version}</version>
<classifier>${javafx.classifier}</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>${javafx.version}</version>
<classifier>${javafx.classifier}</classifier>
</dependency>
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>11.1.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>de.jensd</groupId>
<artifactId>fontawesomefx</artifactId>
<version>8.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>io.github.palexdev</groupId>
<artifactId>scenicview</artifactId>
<version>17.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.1.4</version>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.3.3</version>
</dependency>
</dependencies>
Output of mvn dependency:tree:
com.mypackage:artifact_CustomerApp:jar:1.1-SNAPSHOT
+- org.openjfx:javafx-controls:jar:win:20.0.2:compile
| \- org.openjfx:javafx-graphics:jar:20.0.2:compile
+- org.openjfx:javafx-fxml:jar:win:20.0.2:compile
| \- org.openjfx:javafx-controls:jar:20.0.2:compile
+- org.openjfx:javafx-graphics:jar:win:20.0.2:compile
| \- org.openjfx:javafx-base:jar:20.0.2:compile
| \- org.openjfx:javafx-base:jar:win:20.0.2:compile
+- org.openjfx:javafx-web:jar:win:20.0.2:compile
| \- org.openjfx:javafx-media:jar:20.0.2:compile
| \- org.openjfx:javafx-media:jar:win:20.0.2:compile
+- org.openjfx:javafx-swing:jar:win:20.0.2:compile
+- org.controlsfx:controlsfx:jar:11.1.2:compile
+- org.junit.jupiter:junit-jupiter-api:jar:5.9.2:test
| +- org.opentest4j:opentest4j:jar:1.2.0:test
| +- org.junit.platform:junit-platform-commons:jar:1.10.1:test
| \- org.apiguardian:apiguardian-api:jar:1.1.2:test
+- org.junit.jupiter:junit-jupiter-engine:jar:5.9.2:test
| \- org.junit.platform:junit-platform-engine:jar:1.10.1:test
+- org.projectlombok:lombok:jar:1.18.28:compile
+- org.hsqldb:hsqldb:jar:2.7.2:compile
+- jakarta.persistence:jakarta.persistence-api:jar:3.1.0:compile
+- com.fasterxml.jackson.core:jackson-databind:jar:2.15.2:compile
| +- com.fasterxml.jackson.core:jackson-annotations:jar:2.15.3:compile
| \- com.fasterxml.jackson.core:jackson-core:jar:2.15.3:compile
+- de.jensd:fontawesomefx:jar:8.9:compile
+- org.springframework.boot:spring-boot-starter-test:jar:3.2.2:test
| +- org.springframework.boot:spring-boot-starter:jar:3.2.2:compile
| | +- org.springframework.boot:spring-boot:jar:3.2.2:compile
| | +- org.springframework.boot:spring-boot-autoconfigure:jar:3.2.2:compile
| | +- org.springframework.boot:spring-boot-starter-logging:jar:3.2.2:compile
| | | +- ch.qos.logback:logback-classic:jar:1.4.14:compile
| | | | \- ch.qos.logback:logback-core:jar:1.4.14:compile
| | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.21.1:compile
| | | | \- org.apache.logging.log4j:log4j-api:jar:2.21.1:compile
| | | \- org.slf4j:jul-to-slf4j:jar:2.0.11:compile
| | \- org.yaml:snakeyaml:jar:2.2:compile
| +- org.springframework.boot:spring-boot-test:jar:3.2.2:test
| +- org.springframework.boot:spring-boot-test-autoconfigure:jar:3.2.2:test
| +- com.jayway.jsonpath:json-path:jar:2.8.0:test
| +- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.1:compile
| | \- jakarta.activation:jakarta.activation-api:jar:2.1.2:compile
| +- net.minidev:json-smart:jar:2.5.0:test
| | \- net.minidev:accessors-smart:jar:2.5.0:test
| | \- org.ow2.asm:asm:jar:9.3:test
| +- org.assertj:assertj-core:jar:3.24.2:test
| | \- net.bytebuddy:byte-buddy:jar:1.14.11:runtime
| +- org.awaitility:awaitility:jar:4.2.0:test
| +- org.hamcrest:hamcrest:jar:2.2:test
| +- org.junit.jupiter:junit-jupiter:jar:5.10.1:test
| | \- org.junit.jupiter:junit-jupiter-params:jar:5.10.1:test
| +- org.mockito:mockito-core:jar:5.7.0:test
| | +- net.bytebuddy:byte-buddy-agent:jar:1.14.11:test
| | \- org.objenesis:objenesis:jar:3.3:test
| +- org.mockito:mockito-junit-jupiter:jar:5.7.0:test
| +- org.skyscreamer:jsonassert:jar:1.5.1:test
| | \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
| +- org.springframework:spring-core:jar:6.1.3:compile
| | \- org.springframework:spring-jcl:jar:6.1.3:compile
| +- org.springframework:spring-test:jar:6.1.3:test
| \- org.xmlunit:xmlunit-core:jar:2.9.1:test
+- org.springframework.restdocs:spring-restdocs-mockmvc:jar:3.0.0:test
| +- org.springframework.restdocs:spring-restdocs-core:jar:3.0.1:test
| +- org.springframework:spring-webmvc:jar:6.1.3:compile
| | \- org.springframework:spring-expression:jar:6.1.3:compile
| \- jakarta.servlet:jakarta.servlet-api:jar:6.0.0:test
+- org.springframework.boot:spring-boot-starter-web:jar:3.2.2:compile
| +- org.springframework.boot:spring-boot-starter-json:jar:3.2.2:compile
| | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.15.3:compile
| | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.15.3:compile
| | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.15.3:compile
| +- org.springframework.boot:spring-boot-starter-tomcat:jar:3.2.2:compile
| | +- org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.18:compile
| | +- org.apache.tomcat.embed:tomcat-embed-el:jar:10.1.18:compile
| | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:10.1.18:compile
| \- org.springframework:spring-web:jar:6.1.3:compile
| \- io.micrometer:micrometer-observation:jar:1.12.2:compile
| \- io.micrometer:micrometer-commons:jar:1.12.2:compile
+- org.springframework.boot:spring-boot-starter-data-jpa:jar:3.1.4:compile
| +- org.springframework.boot:spring-boot-starter-aop:jar:3.2.2:compile
| | \- org.aspectj:aspectjweaver:jar:1.9.21:compile
| +- org.springframework.boot:spring-boot-starter-jdbc:jar:3.2.2:compile
| | \- com.zaxxer:HikariCP:jar:5.0.1:compile
| +- org.hibernate.orm:hibernate-core:jar:6.4.1.Final:compile
| | +- jakarta.transaction:jakarta.transaction-api:jar:2.0.1:compile
| | +- org.jboss.logging:jboss-logging:jar:3.5.3.Final:runtime
| | +- org.hibernate.common:hibernate-commons-annotations:jar:6.0.6.Final:runtime
| | +- io.smallrye:jandex:jar:3.1.2:runtime
| | +- com.fasterxml:classmate:jar:1.6.0:runtime
| | +- org.glassfish.jaxb:jaxb-runtime:jar:4.0.4:runtime
| | | \- org.glassfish.jaxb:jaxb-core:jar:4.0.4:runtime
| | | +- org.eclipse.angus:angus-activation:jar:2.0.1:runtime
| | | +- org.glassfish.jaxb:txw2:jar:4.0.4:runtime
| | | \- com.sun.istack:istack-commons-runtime:jar:4.1.2:runtime
| | \- jakarta.inject:jakarta.inject-api:jar:2.0.1:runtime
| \- org.springframework:spring-aspects:jar:6.1.3:compile
+- io.github.palexdev:scenicview:jar:17.0.2:compile
| +- org.openjfx:javafx-base:jar:linux:18:runtime
| +- org.openjfx:javafx-graphics:jar:linux:18:runtime
| +- org.openjfx:javafx-fxml:jar:linux:18:runtime
| \- org.openjfx:javafx-controls:jar:linux:18:runtime
+- org.springframework.data:spring-data-jpa:jar:3.1.4:compile
| +- org.springframework.data:spring-data-commons:jar:3.2.2:compile
| +- org.springframework:spring-orm:jar:6.1.3:compile
| +- org.springframework:spring-context:jar:6.1.3:compile
| +- org.springframework:spring-aop:jar:6.1.3:compile
| +- org.springframework:spring-tx:jar:6.1.3:compile
| +- org.springframework:spring-beans:jar:6.1.3:compile
| +- org.antlr:antlr4-runtime:jar:4.10.1:compile
| +- jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile
| \- org.slf4j:slf4j-api:jar:2.0.11:compile
+- org.springdoc:springdoc-openapi-starter-webmvc-ui:jar:2.2.0:compile
| +- org.springdoc:springdoc-openapi-starter-webmvc-api:jar:2.2.0:compile
| | \- org.springdoc:springdoc-openapi-starter-common:jar:2.2.0:compile
| | \- io.swagger.core.v3:swagger-core-jakarta:jar:2.2.15:compile
| | +- org.apache.commons:commons-lang3:jar:3.13.0:compile
| | +- io.swagger.core.v3:swagger-annotations-jakarta:jar:2.2.15:compile
| | +- io.swagger.core.v3:swagger-models-jakarta:jar:2.2.15:compile
| | +- jakarta.validation:jakarta.validation-api:jar:3.0.2:compile
| | \- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:jar:2.15.3:compile
| \- org.webjars:swagger-ui:jar:5.2.0:compile
+- javax.annotation:javax.annotation-api:jar:1.3.2:compile
+- javax.xml.bind:jaxb-api:jar:2.3.1:compile
| \- javax.activation:javax.activation-api:jar:1.2.0:compile
+- org.springframework:spring-jdbc:jar:6.1.4:compile
\- org.mariadb.jdbc:mariadb-java-client:jar:3.3.3:compile
\- com.github.waffle:waffle-jna:jar:3.3.0:compile
+- net.java.dev.jna:jna:jar:5.13.0:compile
+- net.java.dev.jna:jna-platform:jar:5.13.0:compile
+- org.slf4j:jcl-over-slf4j:jar:2.0.11:compile
+- com.github.ben-manes.caffeine:caffeine:jar:3.1.8:compile
| \- com.google.errorprone:error_prone_annotations:jar:2.21.1:compile
\- org.checkerframework:checker-qual:jar:3.32.0:compile
You have defined a java platform module which relies on a modular version of the slf4j library, but does not require slf4j in the module.
Note: slf4j was only modularized in version 2 of that library.
Fix Alternative: for a modular app
Add the following to your module-info.java:
requires slf4j;
As noted in comments by the asker:
Adding "requires org.slf4j;" resolved the issue.
Fix Alternative: for a non-modular app
Delete the module-info.java from your application, making the application non-modular. Load the JavaFX libraries as modules from the JavaFX SDK by adding them to the module path.
Instructions for non-modular JavaFX applications are in the getting started instructions at openjfx.io and are also provided in the "Testing" section of this answer.
Your module is not well-defined
When you have a module which tries to use classes on the module path but does not require them or appropriately load them via the service mechanism, the module system will limit the accessibility to classes in the module you are trying to use, and they will not be usable.
Reporting a class name by fully qualifying it in the form <module-name>/<package-name>.<class-name> is indicative that the class has been loaded from a module.
As this appears in your stack trace:
com.mypackage/com.mypackage.CustomerApp
it means that have created a modular application by defining a module-info.java (not provided in your question) with your module named com.mypackage and loaded that module from the module path.
I cannot reproduce your issue once the application is made non-modular.
To attempt to reproduce, I:
@SpringBootApplication annotation to the generated application class.module-info.java.It just worked, no issue with logging.
Don't make Spring 6 applications modular
For SpringBoot 3 or Spring 6 applications I strongly recommend not making your application modular.
The Spring software in those versions are defined as automatic modules. Automatic modules modules cannot fully exploit benefits of the module system, especially when some software they rely on is loaded from the classpath. Automatic modules can still confusingly mix loading of software from the classpath and module path, they do not allow module dependencies to be easily analyzed via module dependency analysis tools, they don't enforce all constraints needed to ensure well-defined modules for all software in your application and they can't be linked via jlink.
Defining a Spring 6 application as a modular application provides little benefit to you as a developer and complicates application development for you. You suffer the pain of trying to create a well-defined modular application while receiving little of the benefit of the module system. In the worst cases, some software used by Spring (likely not Spring itself) will be incompatible with the Java module system because, for instance, the software splits packages across jar files.
Follow instructions for non-modular apps at openjfx.io getting started, delete your module-info.java.
Use separate application classes for JavaFX and SpringBoot
I don't recommend making the JavaFX application also a SpringBoot application. (This is not the cause of the error in your question.)
Create two different classes for SpringBoot and JavaFX.
The JavaFX launcher and the SpringBoot runner create new instances of a class. You end up with two instances of the same application class when you use the same class for everything. That could be confusing, even though it works.
Seperation of the SpringBoot and JavaFX application is also good from a Seperation of Concerns software design viewpoint.
To be honest, it looks like that "Maven" and "Gradle" stuff is quite… unstable.
Probably unstable isn't the work you were looking for.
Gradle can be a bit an unstable in my experience in that it can change in breaking ways between version releases, but it is still quite popular despite that.
Maven is quite stable as it hasn't had a major release in years.
Similarly, the gradle and maven plugins for JavaFX haven't changed much over the years.
Maven and Gradle are the primary way to build Java applications and usually OK IMO. But most Java applications are server applications or libraries which are not jlinked and are not client applications which might require a native installer like JavaFX applications. So their packaging is usually less complex.
I'm looking for a way to "mvn javafx:jlink" an application using the MariaDB driver but it's seemingly not even possible… Always get the message that it can't find the module "org.mariadb.jdbc" even though it is there, it's included to the pom.xml successfully and the program itself (through IntelliJ and as a regular "JAR" file using a runscript to add a module path for JavaFX and MariaDB) works… Maven clearly isn't a good way to build/bundle applications, sadly…
This question wasn't about jlink. jlink does not work with automatic modules like the MariaDB JDBC driver. That is a restriction of the jlink tool not Maven, which acts as a shell for the jlink tool. It is also the fault of the mariadb developers that they only offer their software as an automatic module rather than a full module.
The Gradle jlink plugin can package automatic modules.