spring - 使用 Spring Batch 创建一个 @JobScope @Service 来保存作业的共享内存?
问题描述
本质上,我要做的是创建一个@Service 或组件,将一些数据从数据库表中加载到内存中,该数据库表在整个作业执行过程中都会被引用
package com.squareup.se.bridge.batchworker.components.context;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import com.squareup.se.bridge.batchworker.repositories.BridgeBatchJobParametersRepository;
import com.squareup.se.bridge.batchworker.util.JobParameterKeys;
import com.squareup.se.bridge.core.api.services.batchworker.FatalSyncException;
import com.squareup.se.bridge.core.integration.util.logger.JobExecutionLoggerFactory;
import java.io.IOException;
import javax.validation.constraints.NotNull;
import org.slf4j.Logger;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.stereotype.Component;
@JobScope @Component public class BridgeBatchIntegrationJobContextProvider
implements JobExecutionListener {
private Logger logger;
private ObjectMapper mapper;
private BridgeBatchJobParametersRepository bridgeBatchJobParametersRepository;
private BridgeIntegrationJobContext context;
public BridgeBatchIntegrationJobContextProvider(ObjectMapper mapper,
BridgeBatchJobParametersRepository bridgeBatchJobParametersRepository) {
this.mapper = mapper;
this.bridgeBatchJobParametersRepository = bridgeBatchJobParametersRepository;
}
@Override public void beforeJob(JobExecution jobExecution) {
var jobId = jobExecution.getJobParameters().getString(JobParameterKeys.SYNC_ID);
this.logger = JobExecutionLoggerFactory.getLogger(
BridgeBatchIntegrationJobContextProvider.class, jobId);
this.context = deserializeJobParameters(jobId);
}
@NotNull public BridgeIntegrationJobContext get() {
if (context == null) {
throw new IllegalStateException("Expected context to exist before calling this method");
}
return context;
}
@Override public void afterJob(JobExecution jobExecution) { }
@NotNull private String getParameters(String jobId) {
var jobParams = bridgeBatchJobParametersRepository.find(jobId);
if (jobParams == null || jobParams.size() == 0) {
throw new FatalSyncException(String.format("No job parameters for job `%s` exists", jobId));
}
if (jobParams.size() > 1) {
throw new FatalSyncException(String.format("Multiple parameter entries exist for job `%s`",
jobId));
} else if (Strings.isNullOrEmpty(jobParams.get(0).getIntegrationContext())) {
throw new FatalSyncException(String.format("Job parameters for job `%s` is empty", jobId));
}
return jobParams.get(0).getIntegrationContext();
}
@NotNull private BridgeIntegrationJobContext deserializeJobParameters(String jobId) {
try {
return mapper.readValue(getParameters(jobId),
BridgeIntegrationJobContext.class);
} catch (IOException e) {
//TODO page on this
logger.info(e.getMessage(), e);
throw new FatalSyncException(e);
}
}
}
我已经配置了这样的工作:
return jobBuilderFactory.get(CUSTOMERS_BATCH_JOB_NAME)
.incrementer(new RunIdIncrementer())
.start(loadFromOriginStep)
.next(retryFailuresFromOriginStep)
.listener(bridgeBatchIntegrationJobContextProvider)
.listener(jobListener)
.build();
构造函数依赖于其他 bean,包括 jackson 对象映射器和 JPA 存储库。我遇到了一些问题:
- Spring没有实例化构造函数,因此我要绑定的实例变量不存在
如果我从组件中删除 @JobScope,Spring 会构造组件实例。
解决方案
我看不到@JobContext
您的代码在哪里使用,根据您的要求,您不需要它。
如果您想使用侦听器在作业执行上下文中加载一些数据,您可以beforeJob
使用jobExecution.getExecutionContext().put("key", "value");
.
也就是说,不建议在执行上下文中加载大量数据,因为它在步骤之间保持不变。
因此,除非您在执行上下文中加载少量数据,否则您需要找到另一种方法(例如使用单独的缓存,请参阅Spring Batch With Annotation and Caching)。
推荐阅读
- python-3.x - 如何在 PySimpleGUI 中重置 FileBrowse 或将 FileBrowse 设置为给定路径?
- git - 如何删除 git commit?
- python - 如果用户输入在列表中,如何从列表中删除元素?
- flutter - Flutter 如何将模型对象转换为另一个模型以将其保存到 HIVE
- reactjs - Apex 图表 - 限制缩小
- python - 如何在 Python 代码中从 Visual SFM 读取 .mat 文件?
- android - 通过 fetch、XHR 和 axios 在 React Native 中上传文件在 Android 上失败,但在 iOS 上有效
- javascript - 我无法弄清楚 Firebase 身份验证
- reactjs - 世博会日历警报问题
- python - 使用 Python 对 BigQuery API REST 进行身份验证问题