Весенняя партия не десериализует даты - PullRequest
0 голосов
/ 02 ноября 2018

Я добавляю объект в контекст JobExecution пакета Spring, который содержит поле Instant.

Он сериализуется следующим образом:

{
  "startFrom": {
    "nano": 0,
    "epochSecond": 1541116800
   }
 }

Однако Spring Batch, похоже, не в состоянии десериализовать его.

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

При проведении некоторых исследований я вижу, что у Джексона есть JavaTimeModule для сериализации / десериализации Instant и других классов дат. Однако в классе Jackson2ExecutionContextStringSerializer он создает ObjectMapper следующим образом, не регистрируя нужный модуль:

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? Может быть, есть решение этой проблемы?

Спасибо!

Edit:

Я нашел, как переписать этот объект сопоставления:

  @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();
  }

Однако даже при этом проблема сохраняется.

Ответы [ 2 ]

0 голосов
/ 09 июля 2019

Я заметил похожие проблемы. Мне нужно настроить ObjectMapper, чтобы добавить KotlinModule для работы с классами данных kotlin. К сожалению, способ написания Jackson2ExecutionContextStringSerializer в настоящее время не очень расширяем. Как вы видели из созданного по умолчанию ObjectMapper, были добавлены некоторые настройки по умолчанию, включая исправление проблем десериализации с параметрами задания: https://jira.spring.io/browse/BATCH-2680.

JobParametersModule, который они устанавливают, это класс private, и поэтому мы не можем настроить ObjectMapper с теми же функциями и добавить к нему.

Я поднял вопрос об этом в Jira: https://jira.spring.io/browse/BATCH-2828

0 голосов
/ 02 ноября 2018

Код, который вы показали, является инициализацией сериализатора по умолчанию. Вы можете переопределить его, предоставив пользовательский сопоставитель объектов, который вы предварительно настроите с необходимыми модулями. Вот пример:

@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();
}

Надеюсь, это поможет.

...