Migration to Spring Boot 2 and using Spring Batch 4

前端 未结 3 495
心在旅途
心在旅途 2020-12-09 23:46

I am migrating Spring Boot from 1.4.2 to 2.0.0, which also includes migrating Spring batch from 3.0.7 to 4.0.0 and it looks like batch process is no longer working when i tr

相关标签:
3条回答
  • 2020-12-10 00:25

    In the solution by @anotherdave and @michael-minella, you could also replace the plain XStreamExecutionContextStringSerializer with an instance of the following class. It accepts both formats when deserializing and serializes to the new format.

    import java.io.BufferedInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.Map;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import org.springframework.batch.core.repository.ExecutionContextSerializer;
    import org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer;
    import org.springframework.batch.core.repository.dao.XStreamExecutionContextStringSerializer;
    
    
    /**
     * Enables Spring Batch 4 to read both ExecutionContext entries written by ealier versions and the Spring 5 format. Entries are
     * written in Spring 5 format.
     */
    @SuppressWarnings("deprecation")
    class XStreamOrJackson2ExecutionContextSerializer implements ExecutionContextSerializer {
        private final XStreamExecutionContextStringSerializer xStream = new XStreamExecutionContextStringSerializer();
        private final Jackson2ExecutionContextStringSerializer jackson = new Jackson2ExecutionContextStringSerializer();
    
        public XStreamOrJackson2ExecutionContextSerializer() throws Exception {
            xStream.afterPropertiesSet();
        }
    
        // The caller closes the stream; and the decoration by ensureMarkSupported does not need any cleanup.
        @SuppressWarnings("resource")
        @Override
        public Map<String, Object> deserialize(InputStream inputStream) throws IOException {
            InputStream repeatableInputStream = ensureMarkSupported(inputStream);
            repeatableInputStream.mark(Integer.MAX_VALUE);
    
            try {
                return jackson.deserialize(repeatableInputStream);
            } catch (JsonProcessingException e) {
                repeatableInputStream.reset();
                return xStream.deserialize(repeatableInputStream);
            }
        }
    
        private static InputStream ensureMarkSupported(InputStream in) {
            return in.markSupported() ? in : new BufferedInputStream(in);
        }
    
        @Override
        public void serialize(Map<String, Object> object, OutputStream outputStream) throws IOException {
            jackson.serialize(object, outputStream);
        }
    }
    
    0 讨论(0)
  • 2020-12-10 00:34

    Before Spring Batch 4, the default serialization mechanism for the ExecutionContext was via XStream. Now it uses Jackson by default which is not compatible with the old serialization format. We still have the old version available (XStreamExecutionContextStringSerializer) but you'll need to configure it yourself by implementing a BatchConfigurer and overriding the configuration in the JobRepositoryFactoryBean.

    For the record, this is related to this issue: https://jira.spring.io/browse/BATCH-2575.

    0 讨论(0)
  • 2020-12-10 00:35

    Based on Michael's answer above, this code block worked for me to extend the default configuration — I had to wire up the Serializer to both the JobRepository.class and the JobExplorer.class:

    @Configuration
    @EnableBatchProcessing
    MyBatchConfigurer extends DefaultBatchConfigurer {
        private final DataSource dataSource;
    
        @Autowired
        public BatchConfiguration(final DataSource dataSource) throws Exception {
            this.dataSource = dataSource;
        }
    
        @Bean
        ExecutionContextSerializer getSerializer() {
            return new XStreamExecutionContextStringSerializer();
        }
    
    
        @Override
        protected JobRepository createJobRepository() throws Exception {
            final JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
            factory.setDataSource(dataSource);
            factory.setSerializer(getSerializer());
            factory.setTransactionManager(getTransactionManager());
            factory.afterPropertiesSet();
            return factory.getObject();
        }
    
        @Override
        protected JobExplorer createJobExplorer() throws Exception {
            final JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
            jobExplorerFactoryBean.setDataSource(dataSource);
            jobExplorerFactoryBean.setSerializer(getSerializer());
            jobExplorerFactoryBean.afterPropertiesSet();
            return jobExplorerFactoryBean.getObject();
        }
    }
    
    0 讨论(0)
提交回复
热议问题