У меня есть проект JavaFX, и я использую Maven для управления зависимостями. Все работает нормально, пока я не добавлю зависимость maven для «mariadb-java-client», чтобы получить драйвер JDBC MariaDB. Затем я получаю ошибку "java.lang.NoClassDefFoundError: org.slf4j.Logger".
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.3.3</version>
</dependency>
Я получаю следующую ошибку:
Exception in Application init method
Exception in thread "main" java.lang.RuntimeException: Exception in Application init method
at [email protected]/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:888)
at [email protected]/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 [email protected]/org.springframework.boot.SpringApplication.<clinit>(SpringApplication.java:202)
at com.mypackage/com.mypackage.CustomerApp.init(CustomerApp.java:72)
at [email protected]/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
Ошибка выдается при запуске приложения. Единственная строка кода в моем коде от точки трассировки стека до строки 72 в CustomerApp.java, которая представляет собой следующий фрагмент кода на этапе инициализации приложения, где я установил контекст Spring:
@Override
public void init() throws Exception {
springContext = SpringApplication.run(CustomerApp.class);
}
Я перепробовал все, что нашел в предыдущих вопросах. Я пытался добавить "slf4j-api", "slf4j-log4j12", "slf4j-simple" и т. д.
Ничего не помогло.
Мои зависимости в 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>
Вывод 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
@James_D Это полная трассировка стека. Ошибка выдается при запуске приложения при настройке контекста Spring. Я дополню свой вопрос информацией, но не думаю, что это будет слишком полезно.
Возможно, было бы полезно хотя бы посмотреть, создаете ли вы регистратор, создаете что-то с помощью Spring (это может быть создание регистратора) или создаете что-то, связанное с базой данных (что может привести к тому, что mariadb создаст регистратор). Обратите внимание, что в mariadb, а также в библиотеках Spring существует зависимость slf4j: я предполагаю, что они каким-то образом конфликтуют. Вы пытались исключить эту зависимость из зависимости mariadb? (Это всего лишь предположение...)
@James_D Я добавил в вопрос фрагмент кода из строки трассировки стека. Я попытался исключить все зависимости SLF4J пакета mariadb и даже пакета jna waffle, который является транзитивной зависимостью mariadb. Но у меня все та же ошибка.
@jewelsea Спасибо. Это действительно было вызвано отсутствием определения в файле mod-info.java. Добавление «требуется org.slf4j;» решил проблему. Теперь я чувствую себя глупо, пропустив это, но сообщение об ошибке смутило меня и привело меня в кроличью нору добавления зависимостей, исключений и т. д., о которых я совершенно забыл об этом. Еще раз спасибо. Напишите ответ, я отмечу его как правильный.




Вы определили модуль платформы Java, который основан на модульной версии библиотеки slf4j, но не требует наличия slf4j в модуле.
Примечание: slf4j был модульным только во второй версии этой библиотеки.
Альтернатива исправлению: для модульного приложения
Добавьте в свой module-info.java следующее:
requires slf4j;
Как отмечено в комментариях спрашивающего:
Добавление «требуется org.slf4j;» решил проблему.
Альтернатива исправлению: для немодульного приложения
Удалите module-info.java из своего приложения, сделав приложение немодульным. Загрузите библиотеки JavaFX как модули из JavaFX SDK, добавив их в путь к модулю.
Инструкции для немодульных приложений JavaFX приведены в инструкциях по началу работы на сайте openjfx.io, а также в разделе «Тестирование» этого ответа.
Ваш модуль не четко определен
Если у вас есть модуль, который пытается использовать классы в пути к модулю, но не требует их и не загружает их соответствующим образом через механизм службы, система модулей ограничит доступ к классам в модуле, который вы пытаетесь использовать, и они не будут быть пригодным для использования.
Сообщение имени класса путем его полного указания в форме <module-name>/<package-name>.<class-name> указывает на то, что класс был загружен из модуля.
Как это отображается в трассировке стека:
com.mypackage/com.mypackage.CustomerApp
это означает, что вы создали модульное приложение, определив module-info.java (не указанный в вашем вопросе) с вашим модулем с именем com.mypackage и загрузив этот модуль по пути к модулю.
Я не могу воспроизвести вашу проблему, если приложение сделано немодульным.
Чтобы попытаться воспроизвести, я:
@SpringBootApplication к сгенерированному классу приложения.module-info.java.Все заработало, проблем с регистрацией нет.
Не делайте приложения Spring 6 модульными
Для приложений SpringBoot 3 или Spring 6 я настоятельно рекомендую не делать ваше приложение модульным.
Программное обеспечение Spring в этих версиях определяется как автоматические модули. Модули автоматических модулей не могут в полной мере использовать преимущества модульной системы, особенно когда какое-то программное обеспечение, на которое они полагаются, загружается из пути к классам. Автоматические модули по-прежнему могут сбивать с толку загрузку программного обеспечения из пути к классам и пути к модулю, они не позволяют легко анализировать зависимости модулей с помощью инструментов анализа зависимостей модулей, они не накладывают все ограничения, необходимые для обеспечения четко определенных модулей для всего программного обеспечения в ваше приложение, и они не могут быть связаны через jlink.
Определение приложения Spring 6 как модульного приложения мало что дает вам как разработчику и усложняет разработку приложения. Вы страдаете от попыток создать четко определенное модульное приложение, не получая при этом никакой пользы от модульной системы. В худшем случае некоторое программное обеспечение, используемое Spring (вероятно, не сам Spring), будет несовместимо с системой модулей Java, поскольку, например, программное обеспечение разбивает пакеты на файлы jar.
Следуйте инструкциям для немодульных приложений на сайте openjfx.io. Для начала удалите свой module-info.java.
Используйте отдельные классы приложений для JavaFX и SpringBoot.
Я не рекомендую делать приложение JavaFX также приложением SpringBoot. (Это не причина ошибки в вашем вопросе.)
Создайте два разных класса для SpringBoot и JavaFX.
Средство запуска JavaFX и средство запуска SpringBoot создают новые экземпляры класса. Если вы используете один и тот же класс для всего, вы получите два экземпляра одного и того же класса приложения. Это может сбить с толку, хотя это работает.
Разделение приложений SpringBoot и JavaFX также хорошо с точки зрения разделения задач при разработке программного обеспечения.
Спасибо за ваш ответ и очень хорошее объяснение. Я обязательно рассмотрю, как улучшить работу JavaFX с Spring Boot.
Не могли бы вы опубликовать код, вызывающий исключение? Это полная трассировка стека?