英文:
Maven shade IllegalStateException - Required class information is missing
问题
我刚刚使用JavaFX和Hibernate构建了一个应用程序,在IntelliJ上构建和运行都很完美,所以我选择使用Maven Shade插件生成了一个"fat-jar",因为我使用了一些带有自动模块名称的库,所以无法使用jlink。
Jar文件创建成功,它可以正确加载初始屏幕,但是当它尝试连接到我的数据库时,特别是以下这一行出现问题(JPAUtil.java:19):
factory = Persistence.createEntityManagerFactory(persistenceUnit, properties);
我收到以下异常:
java.lang.IllegalStateException: 缺少所需的类信息
at org.jboss.jandex.Indexer.rebuildNestedType(Indexer.java:926)
at org.jboss.jandex.Indexer.resolveTypePath(Indexer.java:786)
...
...
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
...
...
at java.base/java.lang.Thread.run(Thread.java:834)
我知道语法是正确的,正如我之前提到的,它在IDE上运行得很好,所以我怀疑在由Shade生成的jar文件中可能缺少了一些东西,然而我已经花了将近3天的时间来解决这个问题,但是我根本找不到原因。堆栈跟踪上显示的信息帮助不大,至少我没有看到任何有用的内容 - 我甚至检查了堆栈跟踪中提到的所有类,它们似乎都在生成的Jar中。
希望这里有人遇到过类似的问题,或者对Maven Shade过程比我更熟悉。如果有任何帮助或者要注意的地方,请告诉我。
英文:
I just finished building an application using JavaFX and Hibernate, which builds and run perfectly on IntelliJ, so I choose to generate a "fat-jar" using maven shade plugin, since I make use of some libraries with automatic module names, so I cannot use jlink.
Jar is created fine, it loads the initial screen correctly, however when it tries to make connection to my database, specifically this line is the problematic (JPAUtil.java:19);
factory = Persistence.createEntityManagerFactory(persistenceUnit, properties);
I get the following exceptions;
java.lang.IllegalStateException: Required class information is missing
at org.jboss.jandex.Indexer.rebuildNestedType(Indexer.java:926)
at org.jboss.jandex.Indexer.resolveTypePath(Indexer.java:786)
at org.jboss.jandex.Indexer.resolveTypeAnnotation(Indexer.java:705)
at org.jboss.jandex.Indexer.resolveTypeAnnotations(Indexer.java:613)
at org.jboss.jandex.Indexer.index(Indexer.java:1602)
at org.hibernate.boot.archive.scan.spi.ClassFileArchiveEntryHandler.toClassDescriptor(ClassFileArchiveEntryHandler.java:64)
at org.hibernate.boot.archive.scan.spi.ClassFileArchiveEntryHandler.handleEntry(ClassFileArchiveEntryHandler.java:52)
at org.hibernate.boot.archive.internal.JarFileBasedArchiveDescriptor.visitArchive(JarFileBasedArchiveDescriptor.java:147)
at org.hibernate.boot.archive.scan.spi.AbstractScannerImpl.scan(AbstractScannerImpl.java:48)
at org.hibernate.boot.model.process.internal.ScanningCoordinator.coordinateScan(ScanningCoordinator.java:76)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.prepare(MetadataBuildingProcess.java:98)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:254)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:175)
at org.hibernate.jpa.boot.spi.Bootstrap.getEntityManagerFactoryBuilder(Bootstrap.java:76)
at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilder(HibernatePersistenceProvider.java:171)
at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:119)
at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:61)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:50)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
at com.it.util.JPAUtil.getEntityManagerFactory(JPAUtil.java:19)
at com.it.controller.HomeController.initializeSettings(HomeController.java:1571)
at com.it.controller.HomeController.initialize(HomeController.java:1407)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2573)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3237)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
at com.it.Home.start(Home.java:23)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:834)
I know the syntax is correct as I mentioned before it runs correctly on IDE, so I suspect it is something missing on the jar file generated by shade, however I've spend almost 3 days on this already and I simply cannot find a reason. Information shown on the stacktrace doesn't help much, at least I don't see anything - I did even looked to all classes mentioned on the stacktrace and they all seem to be on the generated Jar.
Hoping anyone here had something similar or is maybe more familiar than me on the maven shade process. Any help or point to look at would be appreciated.
Additional files which would help to identify the problem is as follow;
persistence.xml - other properties are loaded from a XML file on the code.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="Project-Postgre">
<description>Hibernate JPA Configuration</description>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value = "false" />
</properties>
</persistence-unit>
</persistence>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.it</groupId>
<artifactId>Project</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.release>11</maven.compiler.release>
<javafx.version>14</javafx.version>
</properties>
<name>Project</name>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/de.jensd/fontawesomefx -->
<dependency>
<groupId>de.jensd</groupId>
<artifactId>fontawesomefx</artifactId>
<version>8.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.20.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc10 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc10</artifactId>
<version>19.7.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>${maven.compiler.release}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.3</version>
<configuration>
<mainClass>com.it.HomeFX</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>project-classifier</shadedClassifierName>
<outputFile>target\shade${project.artifactId}.jar</outputFile>
<transformers>
<transformer implementation=
"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.it.HomeFX</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
JPAUtil
public static EntityManagerFactory getEntityManagerFactory(String persistenceUnit, String connectionURL, String user, String password) {
if (factory == null) {
Map<String, String> properties = new HashMap<>();
properties.put("javax.persistence.jdbc.url", connectionURL);
properties.put("javax.persistence.jdbc.user", user);
properties.put("javax.persistence.jdbc.password", password);
factory = Persistence.createEntityManagerFactory(persistenceUnit, properties);
}
return factory;
}
答案1
得分: 2
我使用相同的错误:
spring.version:5.2.7.RELEASE
spring.boot.version:2.3.1.RELEASE
postgresql-version:42.2.16
所有42.2.15之后的postgresql版本都会出现这个问题。版本42.2.14(或更早版本)对我来说正常工作。
英文:
I had the same error using:
spring.version:5.2.7.RELEASE
spring.boot.version:2.3.1.RELEASE
postgresql-version:42.2.16
It happens with all versions of postgres from 42.2.15. Version 42.2.14 (or earlier) works fine for me.
答案2
得分: 1
我遇到了相同的问题。我尝试将PostgreSQL JDBC驱动程序版本降级到42.0.0。异常消失了,一切都正常工作。
英文:
I had the same problem. I tried to downgrade PostgreSQL JDBC driver version to 42.0.0. Exception gone and everything works fine.
答案3
得分: 1
问题是由javac
1.8生成的无效字节码引起的(例如,已知受影响的版本包括AdoptOpenJDK 1.8u222)。
问题内容(附带重现链接):https://github.com/wildfly/jandex/issues/92
修复方法是升级到org.jboss:jandex:2.2.3.Final
,其中包括解决方法(以及一些其他用于类型注释的修复),或者使用Java 11编译器(即javac
11)。
以防万一,org.postgresql:postgresql:42.2.15
触发此问题,因为它在空值验证中使用了Checker Framework,并且包含多个@Nullable
和@NonNull
注释以使验证通过。
即将推出的org.postgresql:42.2.18
和org.postgresql:42.3.0
将具有相关的解决方法,因此它也将与旧的jandex
版本一起工作。
如果您在阅读这里,我建议将forbidden-apis和jandex字节码解析器(例如de.thetaphi.forbiddenapis
和com.github.vlsi.jandex
Gradle插件)添加到您的构建流程中,以便及早捕获无效的字节码(否则可能不会被注意到),特别是如果您仍在使用javac
1.8。
英文:
The issue is caused by invalid bytecode produced by javac
1.8 (e.g. AdoptOpenJDK 1.8u222 is known to be affected).
Here's the issue (with reproducer): https://github.com/wildfly/jandex/issues/92
The fix is to update to org.jboss:jandex:2.2.3.Final
which includes the workaround (and a couple of other fixes for type annotations), or use Java 11 compiler (== javac
11).
Just in case, org.postgresql:postgresql:42.2.15
triggers the issue since it uses the Checker Framework for nullness verification, and it includes multiple @Nullable
and @NonNull
annotations to make the verifications pass.
The upcoming org.postgresql:42.2.18
and org.postgresql:42.3.0
will have the relevant workarounds, so it would work with old jandex
versions as well.
If you are reading here, I would recommend adding forbidden-apis and jandex bytecode parsers (e.g. de.thetaphi.forbiddenapis
and com.github.vlsi.jandex
Gradle plugins) to your build pipeline to capture invalid bytecode early (which might otherwise come unnoticed), especially if you still use javac
1.8.
答案4
得分: 0
我已成功解决了这个问题,方法是从Hibernate切换到了OpenJPA。
Hibernate没有提供足够的信息来调试这个问题,当我切换到OpenJPA时,我只需要将以下内容添加到我的pom.xml文件中:
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>3.1.2</version>
</dependency>
Shade创建了包含所有必需库和与数据库连接的JAR文件,连接成功。
英文:
I have managed to overcome this issue by switching from Hibernate to OpenJPA.
Hibernate did not provide enough information to debug the problem and when switching to OpenJPA I just had to add this to my pom.xml;
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>3.1.2</version>
</dependency>
Shade created the JAR with all required libraries and connection to database was successfully.
答案5
得分: 0
已经在PostgreSQL JDBC驱动程序版本42.2.19中修复,详见https://jdbc.postgresql.org/documentation/changelog.html#version_42.2.19。
将您的版本更新到42.2.19,问题应该会得到解决。
英文:
Eventually, fixed in PostgreSQL JDBC Driver version 42.2.19, see https://jdbc.postgresql.org/documentation/changelog.html#version_42.2.19.
Update your version to 42.2.19 and it should solve the problem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论