Chr*_*ian 7 spring-batch spring-boot
我正在使用 SpringBoot2.4.2和 SpringBatch。反序列化失败并显示以下堆栈跟踪:
2021-03-29 15:51:28.529 ERROR 30308 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalArgumentException: Unable to deserialize the execution context
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:328) ~[spring-batch-core-4.3.1.jar:4.3.1]
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:312) ~[spring-batch-core-4.3.1.jar:4.3.1]
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94) ~[spring-jdbc-5.3.3.jar:5.3.3]
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61) ~[spring-jdbc-5.3.3.jar:5.3.3]
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:723) ~[spring-jdbc-5.3.3.jar:5.3.3]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:651) ~[spring-jdbc-5.3.3.jar:5.3.3]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:713) ~[spring-jdbc-5.3.3.jar:5.3.3]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:744) ~[spring-jdbc-5.3.3.jar:5.3.3]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:757) ~[spring-jdbc-5.3.3.jar:5.3.3]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:815) ~[spring-jdbc-5.3.3.jar:5.3.3]
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.getExecutionContext(JdbcExecutionContextDao.java:129) ~[spring-batch-core-4.3.1.jar:4.3.1]
at org.springframework.batch.core.explore.support.SimpleJobExplorer.getStepExecutionDependencies(SimpleJobExplorer.java:238) ~[spring-batch-core-4.3.1.jar:4.3.1]
at org.springframework.batch.core.explore.support.SimpleJobExplorer.findRunningJobExecutions(SimpleJobExplorer.java:118) ~[spring-batch-core-4.3.1.jar:4.3.1]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128) ~[spring-batch-core-4.3.1.jar:4.3.1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.3.jar:5.3.3]
at com.sun.proxy.$Proxy222.findRunningJobExecutions(Unknown Source) ~[na:na]
at com.xyz.onApplicationEvent(HandleJobsOnAppReady.java:50) ~[classes/:na]
at com.xyz.onApplicationEvent(HandleJobsOnAppReady.java:24) ~[classes/:na]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:426) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.boot.context.event.EventPublishingRunListener.running(EventPublishingRunListener.java:111) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplicationRunListeners.lambda$running$6(SpringApplicationRunListeners.java:79) ~[spring-boot-2.4.2.jar:2.4.2]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na]
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:111) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplicationRunListeners.running(SpringApplicationRunListeners.java:79) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:341) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.2.jar:2.4.2]
at com.xyz.Application.main(XYZApplication.java:18) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:578) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: com.fasterxml.jackson.databind.JsonMappingException: The class with [xyz.Class; and name of [xyz.Class; is not trusted. If you believe this class is safe to deserialize, you can add it to the base set of trusted classes at construction time or provide an explicit mapping using Jackson annotations or a custom ObjectMapper. If the serialization is only done by a trusted source, you can also enable default typing. (through reference chain: java.util.HashMap["partition"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:397) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:356) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase.wrapAndThrow(ContainerDeserializerBase.java:181) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:552) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:377) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:29) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:132) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:99) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserializeWithType(MapDeserializer.java:413) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3513) ~[jackson-databind-2.11.4.jar:2.11.4]
at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.deserialize(Jackson2ExecutionContextStringSerializer.java:133) ~[spring-batch-core-4.3.1.jar:4.3.1]
at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer.deserialize(Jackson2ExecutionContextStringSerializer.java:104) ~[spring-batch-core-4.3.1.jar:4.3.1]
at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:325) ~[spring-batch-core-4.3.1.jar:4.3.1]
... 46 common frames omitted
Caused by: java.lang.IllegalArgumentException: The class with [xyz.Class; and name of [xyz.Class; is not trusted. If you believe this class is safe to deserialize, you can add it to the base set of trusted classes at construction time or provide an explicit mapping using Jackson annotations or a custom ObjectMapper. If the serialization is only done by a trusted source, you can also enable default typing.
at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer$TrustedTypeIdResolver.typeFromId(Jackson2ExecutionContextStringSerializer.java:349) ~[spring-batch-core-4.3.1.jar:4.3.1]
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:154) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:97) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromArray(AsArrayTypeDeserializer.java:53) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:193) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:710) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:542) ~[jackson-databind-2.11.4.jar:2.11.4]
... 57 common frames omitted
Run Code Online (Sandbox Code Playgroud)
这个错误非常清楚,我读了很多相关内容。但是我无法解决它。
我向 BatchConfiguration 添加了该类型的 bean ExecutionContextSerializer,但它似乎不起作用:
@Bean
public ExecutionContextSerializer customSerializer(){
return new Jackson2ExecutionContextStringSerializer(ClassToBeTrusted.class.getName());
}
@Bean
public JobRepository createJobRepository(DataSource dataSource,ExecutionContextSerializer executionContextSerializer) throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(getTransactionManager());
factory.setSerializer(executionContextSerializer);
factory.afterPropertiesSet();
return factory.getObject();
}
Run Code Online (Sandbox Code Playgroud)
该错误发生在以下情况:
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
Set<JobExecution> runningJobExecutions = jobExplorer.findRunningJobExecutions(job.getName());
Run Code Online (Sandbox Code Playgroud)
被执行。
更新:该类现在BatchConfiguration实现该类DefaultBatchConfigurer并覆盖 getJobRepository 和 getJobExplorer (不确定这是否有必要?),如下所示:
@Override
public JobRepository getJobRepository() {
try {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(datasource);
factory.setTransactionManager(getTransactionManager());
factory.setSerializer(customSerializer());
factory.afterPropertiesSet();
return factory.getObject();
}
catch(Exception e){
throw new BatchConfigurationException(e);
}
}
@Override
public JobExplorer getJobExplorer(){
try{
JobExplorerFactoryBean factory = new JobExplorerFactoryBean();
factory.setSerializer(customSerializer());
factory.setDataSource(datasource);
factory.afterPropertiesSet();
return factory.getObject();
}
catch(Exception e ){
throw new BatchConfigurationException(e);
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我仍然看到反序列化错误:Myclass is not trust ...如上所述。
根据Christian 的回答,这是覆盖默认序列化程序的方法。
package com.my.path.to.config;
import com.my.path.to.entity.MyEntity;
import org.springframework.batch.core.configuration.annotation.BatchConfigurer;
import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.explore.support.JobExplorerFactoryBean;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.ExecutionContextSerializer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
public class BatchConfiguration {
@Bean
public ExecutionContextSerializer customSerializer() {
return new Jackson2ExecutionContextStringSerializer(MyEntity.class.getName());
}
@Bean
BatchConfigurer myBatchConfigurer(@Qualifier("batchDataSource") DataSource dataSource,
ExecutionContextSerializer executionContextSerializer,
PlatformTransactionManager transactionManager) {
return new DefaultBatchConfigurer(dataSource) {
@Override
protected JobExplorer createJobExplorer() throws Exception {
JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
jobExplorerFactoryBean.setDataSource(dataSource);
jobExplorerFactoryBean
.setSerializer(executionContextSerializer);
jobExplorerFactoryBean.afterPropertiesSet();
return jobExplorerFactoryBean.getObject();
}
@Override
protected JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
jobRepositoryFactoryBean.setDataSource(dataSource);
jobRepositoryFactoryBean
.setSerializer(executionContextSerializer);
jobRepositoryFactoryBean.setTransactionManager(transactionManager);
jobRepositoryFactoryBean.afterPropertiesSet();
return jobRepositoryFactoryBean.getObject();
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
Jackson2ExecutionContextStringSerializer我可以通过调试及其逻辑来解决问题isTrusted。最后,我必须将类型化数组和类添加到受信任的类列表中,如下所示:
public ExecutionContextSerializer customSerializer() {
return new Jackson2ExecutionContextStringSerializer(new MyClass[0].getClass().getName(), MyClass.class.getName());
}
Run Code Online (Sandbox Code Playgroud)
当我看到[L<fullyQualifiedClassName>与fullyQualifiedClassName
| 归档时间: |
|
| 查看次数: |
10617 次 |
| 最近记录: |