为什么 Spring-content 在启动时产生 IllegalStateException 如果实体有一个标有 @Enumerated 的字段
Why does Spring-content produce an IllegalStateException on startup if an Entity has a field which is marked with @Enumerated
我们正在使用 Spring-content 作为网络应用程序中的文件存储解决方案,并将版本从 1.0.0.M10 升级到 2.1.0。突然我们的微服务拒绝启动,因为它无法加载它的 ApplicationContext,我无法理解为什么。 Spring-content changelog 提到了涉及装饰 ContentStore 本身的注释的重大更改——我们没有——但我读到的没有提到实体 class 上的注释。我做错了什么,或者这是某种错误?
我做了一个简化的示例,它会产生相同类型的异常,因为我不确定是否允许我共享原始源代码。
我的 Spring-内容依赖项。唯一的其他依赖项是在一个新项目上的 lombok、postgres 和 hibernate:
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
我的实体:
@Data
@Table(name = "employee")
public class EmployeeEntity {
@Id
@Column(name = "id")
private UUID employeeId;
@ContentId
@Column(name = "content_id")
private UUID contentId;
@Enumerated(EnumType.STRING)
@Column(name = "employee_type")
private EmployeeType employeeType;
}
枚举:
public enum EmployeeType {
ASSOCIATE,
MANAGER,
DIRECTOR,
EXECUTIVE;
}
我的回购:
public interface IEmployeeRepository extends JpaRepository<EmployeeEntity, UUID> {
}
还有我的 ContentStore:
public interface IEmployeeContentStore extends ContentStore<EmployeeEntity, String> {
}
当我尝试 运行 应用程序或 运行 加载上下文的 JUnit 测试时,我得到一个充满这些错误的控制台,它似乎早在我可以滚动。
at org.springframework.content.commons.mappingcontext.ContentPropertyBuilderVisitor.visitField(ContentPropertyBuilderVisitor.java:143) ~[spring-content-commons-2.1.0.jar:na]
at org.springframework.content.commons.mappingcontext.ClassWalker.accept(ClassWalker.java:24) ~[spring-content-commons-2.1.0.jar:na]
通过将控制台输出捕获到文本文件,这似乎是根异常:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.content.commons.mappingcontext.MappingContext]: Factory method 'mappingContext' threw exception; nested exception is java.lang.WhosebugError
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.18.jar:5.3.18]
... 134 common frames omitted
Caused by: java.lang.WhosebugError: null
at java.base/java.lang.reflect.Field.copy(Field.java:153) ~[na:na]
at java.base/java.lang.reflect.ReflectAccess.copyField(ReflectAccess.java:151) ~[na:na]
at java.base/jdk.internal.reflect.ReflectionFactory.copyField(ReflectionFactory.java:381) ~[na:na]
at java.base/java.lang.Class.copyFields(Class.java:3383) ~[na:na]
at java.base/java.lang.Class.getDeclaredFields(Class.java:2249) ~[na:na]
at org.springframework.content.commons.mappingcontext.ContentPropertyBuilderVisitor.visitClass(ContentPropertyBuilderVisitor.java:48) ~[spring-content-commons-2.1.0.jar:na]
at org.springframework.content.commons.mappingcontext.ClassWalker.accept(ClassWalker.java:17) ~[spring-content-commons-2.1.0.jar:na]
我已将问题追溯到似乎是实体 class 上的 @Enumerated 注释。删除此字段可完全防止异常发生。
我能找到的最接近的解释是,如果 classes 递归地互相调用,那么 WhosebugException 是您所期望的: 然而,这至少不能直接适用,因为我示例中的实体之间没有任何映射。
我尝试过的事情:
- 删除 @Data 以查看 lombok 的 toString() 是否确实是罪魁祸首。 (见上文)
- 使用转换器 class 而不是 @Enumerated
似乎唯一可行的解决方案是将 EmployeeType 更改为字符串,在这种情况下,一切都会正确加载。如果这是唯一的解决方案,那就不太理想了,因为必须重构整个微服务,以便为该字段使用字符串而不是枚举。
任何人都可以指出正确的方向,使枚举字段以这种方式在 ContentStore 中使用的实体中工作吗?非常感谢!
编辑:添加了我最初忽略的 postgres 和 hibernate 依赖项
Arnaud 的 link 指出了正确的解决方案。当 spring-content 依赖项更新为 2.2.0-SNAPSHOT:
时,该服务现在将按预期启动
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs-boot-starter</artifactId>
<version>2.2.0-SNAPSHOT</version>
</dependency>
再次感谢!
我们正在使用 Spring-content 作为网络应用程序中的文件存储解决方案,并将版本从 1.0.0.M10 升级到 2.1.0。突然我们的微服务拒绝启动,因为它无法加载它的 ApplicationContext,我无法理解为什么。 Spring-content changelog 提到了涉及装饰 ContentStore 本身的注释的重大更改——我们没有——但我读到的没有提到实体 class 上的注释。我做错了什么,或者这是某种错误?
我做了一个简化的示例,它会产生相同类型的异常,因为我不确定是否允许我共享原始源代码。
我的 Spring-内容依赖项。唯一的其他依赖项是在一个新项目上的 lombok、postgres 和 hibernate:
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
我的实体:
@Data
@Table(name = "employee")
public class EmployeeEntity {
@Id
@Column(name = "id")
private UUID employeeId;
@ContentId
@Column(name = "content_id")
private UUID contentId;
@Enumerated(EnumType.STRING)
@Column(name = "employee_type")
private EmployeeType employeeType;
}
枚举:
public enum EmployeeType {
ASSOCIATE,
MANAGER,
DIRECTOR,
EXECUTIVE;
}
我的回购:
public interface IEmployeeRepository extends JpaRepository<EmployeeEntity, UUID> {
}
还有我的 ContentStore:
public interface IEmployeeContentStore extends ContentStore<EmployeeEntity, String> {
}
当我尝试 运行 应用程序或 运行 加载上下文的 JUnit 测试时,我得到一个充满这些错误的控制台,它似乎早在我可以滚动。
at org.springframework.content.commons.mappingcontext.ContentPropertyBuilderVisitor.visitField(ContentPropertyBuilderVisitor.java:143) ~[spring-content-commons-2.1.0.jar:na]
at org.springframework.content.commons.mappingcontext.ClassWalker.accept(ClassWalker.java:24) ~[spring-content-commons-2.1.0.jar:na]
通过将控制台输出捕获到文本文件,这似乎是根异常:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.content.commons.mappingcontext.MappingContext]: Factory method 'mappingContext' threw exception; nested exception is java.lang.WhosebugError
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.18.jar:5.3.18]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.18.jar:5.3.18]
... 134 common frames omitted
Caused by: java.lang.WhosebugError: null
at java.base/java.lang.reflect.Field.copy(Field.java:153) ~[na:na]
at java.base/java.lang.reflect.ReflectAccess.copyField(ReflectAccess.java:151) ~[na:na]
at java.base/jdk.internal.reflect.ReflectionFactory.copyField(ReflectionFactory.java:381) ~[na:na]
at java.base/java.lang.Class.copyFields(Class.java:3383) ~[na:na]
at java.base/java.lang.Class.getDeclaredFields(Class.java:2249) ~[na:na]
at org.springframework.content.commons.mappingcontext.ContentPropertyBuilderVisitor.visitClass(ContentPropertyBuilderVisitor.java:48) ~[spring-content-commons-2.1.0.jar:na]
at org.springframework.content.commons.mappingcontext.ClassWalker.accept(ClassWalker.java:17) ~[spring-content-commons-2.1.0.jar:na]
我已将问题追溯到似乎是实体 class 上的 @Enumerated 注释。删除此字段可完全防止异常发生。
我能找到的最接近的解释是,如果 classes 递归地互相调用,那么 WhosebugException 是您所期望的:
我尝试过的事情:
- 删除 @Data 以查看 lombok 的 toString() 是否确实是罪魁祸首。 (见上文)
- 使用转换器 class 而不是 @Enumerated
似乎唯一可行的解决方案是将 EmployeeType 更改为字符串,在这种情况下,一切都会正确加载。如果这是唯一的解决方案,那就不太理想了,因为必须重构整个微服务,以便为该字段使用字符串而不是枚举。
任何人都可以指出正确的方向,使枚举字段以这种方式在 ContentStore 中使用的实体中工作吗?非常感谢!
编辑:添加了我最初忽略的 postgres 和 hibernate 依赖项
Arnaud 的 link 指出了正确的解决方案。当 spring-content 依赖项更新为 2.2.0-SNAPSHOT:
时,该服务现在将按预期启动 <dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs-boot-starter</artifactId>
<version>2.2.0-SNAPSHOT</version>
</dependency>
再次感谢!