迁移到 Spring Boot 2 并使用 Spring Batch 4
Posted
技术标签:
【中文标题】迁移到 Spring Boot 2 并使用 Spring Batch 4【英文标题】:Migration to Spring Boot 2 and using Spring Batch 4 【发布时间】:2018-09-12 11:51:26 【问题描述】:我正在将 Spring Boot 从 1.4.2 迁移到 2.0.0,其中还包括将 Spring 批处理从 3.0.7 迁移到 4.0.0,当我尝试使用新 Spring 运行批处理时,它看起来不再有效批量版本。
当我尝试调试时,我发现批处理尝试从 batch_job_execution_context 获取数据时出现问题。
我可以看到从数据库中获取数据工作正常,但是新版本的批处理无法解析数据库数据
"map":["entry":["string":["name",""],"string":["sender",""],"string": ["id",""],"string":["nav",""],"string":["created",140418]]]
出现此错误:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected VALUE_STRING: need JSON String that contains type id (for subtype of java.lang.Object) at [Source: (ByteArrayInputStream); line: 1, column: 9] (through reference chain: java.util.HashMap["map"])
我发现,当我删除所有批处理元数据表并从头开始重新创建它们时,批处理似乎又可以工作了。元数据 JSON 格式好像变成了这个
"name":"","sender":"145844","id":"","nav":"","created":"160909"
我不想删除旧数据以使其再次工作,那么有什么办法可以解决这个问题吗?
还有其他人尝试过进行此升级吗?很高兴知道是否还有其他我可能没有注意到的重大变化。
谢谢
【问题讨论】:
这可能与jira.spring.io/browse/BATCH-2680有关。你试过 Spring Batch 4.0.1 版吗? @MahmoudBenHassine 我已经尝试过了,但我仍然得到相同的杰克逊 MismatchedInputException。 【参考方案1】:在 Spring Batch 4 之前,ExecutionContext
的默认序列化机制是通过 XStream。现在它默认使用 Jackson,它与旧的序列化格式不兼容。我们仍有可用的旧版本 (XStreamExecutionContextStringSerializer
),但您需要通过实现 BatchConfigurer
并覆盖 JobRepositoryFactoryBean
中的配置来自行配置。
记录在案,这与此问题有关:https://jira.spring.io/browse/BATCH-2575。
【讨论】:
你也可以在这里回答***.com/questions/51688838/… 吗? 我不清楚答案。您能否粘贴一些代码来支持您的答案?刚接触 Spring Batch,很难理解你在说什么【参考方案2】:根据上面迈克尔的回答,这个代码块对我来说是为了扩展默认配置——我必须将 Serializer 连接到 JobRepository.class 和 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();
【讨论】:
非常有帮助的 tnx。但我当前的配置还包括 \@Bean public JobExecutionDao jobExecutionDao() 方法。我不能通过 DefaultBatchConfigurer 覆盖它。有任何想法吗?不确定我可以将它保留为“bean”而不是覆盖【参考方案3】:在@anotherdave 和@michael-minella 的解决方案中,您还可以将普通的XStreamExecutionContextStringSerializer
替换为以下类的实例。它在反序列化和序列化为新格式时接受这两种格式。
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);
【讨论】:
以上是关于迁移到 Spring Boot 2 并使用 Spring Batch 4的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot App 中使用 Jquery 和 FormData 提交表单字段并上传 File 到 Spring MVC Controller
从 Spring Boot 1.5.10 迁移到 2.0.0 时无法解析依赖项
迁移到 Spring Boot 2.2.0 @JsonIgnore 不起作用