【发布时间】:2018-05-18 01:10:40
【问题描述】:
我有一个使用 Spring Batch 定义预设数量的作业的应用程序,这些作业目前都在 XML 中定义。
随着时间的推移,我们会添加更多作业,这需要更新 XML,但是这些作业始终基于同一个父级,并且可以使用简单的 SQL 查询轻松地预先确定。
所以我一直在尝试切换到使用 XML 配置和基于 Java 的配置的某种组合,但很快就会感到困惑。
尽管我们有很多工作,但每个工作定义基本上都属于两个类别之一。所有作业都继承自一个或另一个父作业,并且实际上是相同的,只是名称不同。作业名称用于从数据库中选择不同的数据。
我想出了一些类似于以下的代码,但在使其正常工作时遇到了问题。
完全免责声明,我也不完全确定我会以正确的方式解决这个问题。稍后会详细介绍;一、代码:
@Configuration
@EnableBatchProcessing
public class DynamicJobConfigurer extends DefaultBatchConfigurer implements InitializingBean {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private JobRegistry jobRegistry;
@Autowired
private DataSource dataSource;
@Autowired
private CustomJobDefinitionService customJobDefinitionService;
private Flow injectedFlow1;
private Flow injectedFlow2;
public void setupJobs() throws DuplicateJobException {
List<JobDefinition> jobDefinitions = customJobDefinitionService.getAllJobDefinitions();
for (JobDefinition jobDefinition : jobDefinitions) {
Job job = null;
if (jobDefinition.getType() == 1) {
job = jobBuilderFactory.get(jobDefinition.getName())
.start(injectedFlow1).build()
.build();
} else if (jobDefinition.getType() == 2) {
job = jobBuilderFactory.get(jobDefinition.getName())
.start(injectedFlow2).build()
.build();
}
if (job != null) {
jobRegistry.register(new ReferenceJobFactory(job));
}
}
}
@Override
public void afterPropertiesSet() throws Exception {
setupJobs();
}
public void setInjectedFlow1(Flow injectedFlow1) {
this.injectedFlow1 = injectedFlow1;
}
public void setInjectedFlow2(Flow injectedFlow2) {
this.injectedFlow2 = injectedFlow2;
}
}
我在 XML 中定义了注入的流,就像这样:
<batch:flow id="injectedFlow1">
<batch:step id="InjectedFlow1.Step1" next="InjectedFlow1.Step2">
<batch:flow parent="InjectedFlow.Step1" />
</batch:step>
<batch:step id="InjectedFlow1.Step2">
<batch:flow parent="InjectedFlow.Step2" />
</batch:step>
</batch:flow>
如您所见,我从InitializingBean 的afterPropertiesSet() 方法有效地启动了setupJobs() 方法(旨在动态创建这些作业定义)。我不确定这是否正确。它正在运行,但我不确定是否有更适合此目的的不同入口点。我也不确定@Configuration 注释的意义是什么。
我目前遇到的问题是,当我从JobRegistry 调用register() 时,它会抛出以下IllegalStateException:
要使用默认的 BatchConfigurer,上下文必须包含不超过一个 DataSource,找到 2。
注意:我的项目实际上定义了两个数据源。第一个是默认的 dataSource bean,它连接到 Spring Batch 使用的数据库。第二个数据源是一个外部数据库,第二个数据源包含定义我的作业列表所需的所有信息。但主要的确实使用默认名称“dataSource”,所以我不太确定我还能告诉它使用那个。
【问题讨论】:
-
这些工作有什么不同?
-
@MichaelMinella 在工作定义级别 - 只有工作名称。一个单独的应用程序 POST 到 Spring Batch Admin 端点以根据名称启动作业,然后其中一个步骤使用作业名称从数据源中选择不同的东西。
-
不过,请注意:在我的实际用例中,我们实际上定义了两个不同的流程(基于我在上面的伪代码中称为“类型”的内容)。这两个不同的流程确实有不同的步骤,但每项工作都是其中之一。
-
如果您认为我可以只使用一两个工作,并将“名称”作为工作参数传递,那并不是我真正想要追求的选择。按名称分隔它们确实很重要,因为它允许我们通过 url.com/jobs/JobName 跟踪不同的执行,而不是将所有内容聚集在一起。尽管每份工作都基于一两个父母,但我们实际上总共有近 100 个。我们预计这个数字会随着时间的推移而继续增长。所以你可以明白为什么用 XML 定义它们最终是不可持续的。
-
您是在 Spring Boot 中使用 Spring Batch 还是仅使用 Spring Batch?
标签: java xml spring spring-batch spring-batch-admin