首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring Batch未反序列化日期

Spring Batch未反序列化日期
EN

Stack Overflow用户
提问于 2018-11-02 18:21:28
回答 3查看 1.5K关注 0票数 1

我在spring batch的JobExecution上下文中添加了一个对象,其中包含一个Instant字段。

它的序列化如下所示:

代码语言:javascript
运行
复制
{
  "startFrom": {
    "nano": 0,
    "epochSecond": 1541116800
   }
 }

然而,Spring Batch似乎无法对其进行反序列化。

代码语言:javascript
运行
复制
Caused by: java.lang.IllegalArgumentException: Unable to deserialize the execution context
    at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:325)
    at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao$ExecutionContextRowMapper.mapRow(JdbcExecutionContextDao.java:309)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:93)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60)
    at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:667)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:605)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:657)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:688)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:756)
    at org.springframework.batch.core.repository.dao.JdbcExecutionContextDao.getExecutionContext(JdbcExecutionContextDao.java:112)
    at org.springframework.batch.core.explore.support.SimpleJobExplorer.getJobExecutionDependencies(SimpleJobExplorer.java:202)
    at org.springframework.batch.core.explore.support.SimpleJobExplorer.getJobExecutions(SimpleJobExplorer.java:83)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
    at org.springframework.aop.framework.ReflectiveMethod

在做一些研究时,我发现Jackson有一个序列化/反序列化Instant和其他date类的JavaTimeModule。但是,在Jackson2ExecutionContextStringSerializer类中,它按如下方式创建ObjectMapper,而不是注册正确的模块:

代码语言:javascript
运行
复制
public Jackson2ExecutionContextStringSerializer() {
    this.objectMapper = new ObjectMapper();
    this.objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
    this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
    this.objectMapper.enableDefaultTyping();
    this.objectMapper.registerModule(new JobParametersModule());
}

Spring Batch不使用自动连接的ObjectMapper有什么原因吗?或者是他们不注册JavaTimeModule的原因?有没有解决这个问题的办法?

谢谢!

编辑:

我已经找到了如何重写这个对象映射器:

代码语言:javascript
运行
复制
  @Bean
  public JobRepository createJobRepository() throws Exception {
    ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()).findAndRegisterModules();

    Jackson2ExecutionContextStringSerializer defaultSerializer = new Jackson2ExecutionContextStringSerializer();
    defaultSerializer.setObjectMapper(objectMapper);

    JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
    factory.setDataSource(dataSource);
    factory.setTransactionManager(transactionManager);
    factory.setSerializer(defaultSerializer);
    factory.afterPropertiesSet();
    return factory.getObject();
  }

然而,即使这样,这个问题仍然存在。

EN

回答 3

Stack Overflow用户

发布于 2020-12-04 21:19:39

下面的方法对我很有效。我正在扩展Mahmoud Ben Hassine上面的答案,这个答案对Nicolas Widart不起作用。(我没有足够的名气来评论)。

代码语言:javascript
运行
复制
@Bean
public BatchConfigurer configurer(DataSource dataSource, PlatformTransactionManager transactionManager,
  ObjectMapper objectMapper) {

    return new DefaultBatchConfigurer(dataSource) {
        final Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();

        @Override
        protected JobRepository createJobRepository() throws Exception {
            serializer.setObjectMapper(objectMapper);

            JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
            factory.setDataSource(dataSource);
            factory.setTransactionManager(transactionManager);
            factory.setSerializer(serializer);
            factory.afterPropertiesSet();
            return factory.getObject();
        }

        @Override
        protected JobExplorer createJobExplorer() throws Exception {
            serializer.setObjectMapper(objectMapper);

            JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
            jobExplorerFactoryBean.setSerializer(serializer);
            jobExplorerFactoryBean.setDataSource(dataSource);
            jobExplorerFactoryBean.afterPropertiesSet();
            return jobExplorerFactoryBean.getObject();
        }
    };
}

(我在另一个@Configuration类中定义了一个ObjectMapper bean。)这里重要的是覆盖createJobExplorer()方法并在那里设置正确的ExecutionContextSerializer,因为此方法将在JobExplorerFactoryBean上调用getTarget(),如果没有设置,则将设置一个普通的ExecutionContextSerializer,这会导致您描述的错误。

票数 1
EN

Stack Overflow用户

发布于 2018-11-02 22:22:19

您显示的代码是序列化程序的默认初始化。您可以通过提供一个自定义对象映射器来覆盖它,该映射器预先配置了所需的模块。下面是一个示例:

代码语言:javascript
运行
复制
@Bean
public JobRepository jobRepository() throws Exception {
    ObjectMapper objectMapper = null; // configure the object mapper as required
    Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();
    serializer.setObjectMapper(objectMapper);

    JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
    jobRepositoryFactoryBean.setSerializer(serializer);
    // set other properties on the jobRepositoryFactoryBean
    jobRepositoryFactoryBean.afterPropertiesSet();
    return jobRepositoryFactoryBean.getObject();
}

希望这能有所帮助。

票数 0
EN

Stack Overflow用户

发布于 2019-07-09 17:32:16

更新

Spring batch现在有一个修复,可以让你在解决这个问题后,在内部获得Jackson2ExecutionContextStringSerialier所做的所有默认设置的同时定制你的ObjectMapperhttps://jira.spring.io/browse/BATCH-2828

修复程序在4.2.0中,在撰写本文时,它当前位于RC1

原始答案

我也注意到了类似的问题。我需要定制ObjectMapper来添加用于处理kotlin数据类的KotlinModule。不幸的是,目前编写Jackson2ExecutionContextStringSerializer的方式并不具有很强的可扩展性。正如您从创建的默认ObjectMapper中看到的,添加了一些默认值,包括对作业参数https://jira.spring.io/browse/BATCH-2680的反序列化问题的修复。

他们设置的JobParametersModule是一个private类,因此我们不能设置具有相同功能的ObjectMapper并对其进行添加。

我在Jira中提出了一个问题:https://jira.spring.io/browse/BATCH-2828

解决这个问题的方法是复制并粘贴JobParmetersModule的源代码,这样您就可以在覆盖中注册相同的代码。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53116676

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档