@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,上下文必须包含一个以上的数据源(found 2)。
注意:我的项目实际上定义了两个数据源。第一个是默认的dataSource bean,它连接到Spring批处理使用的数据库。第二个数据源是一个外部数据库,这第二个包含我定义作业列表所需的所有信息。但是主要的一个确实使用了默认名称“DataSource”,所以我不太确定我还可以如何告诉它使用这个名称。
首先,我不推荐使用XML和Java配置的组合。只使用一个,最好是Java一个,因为将XML配置转换为Java配置并不费力。(除非你有一些很好的理由去做--你没有解释)
我并没有单独使用Spring Batch,因为我一直将它与Spring Boot一起使用,并且我有一个项目,在该项目中我定义了多个作业,它对于您所展示的类似代码总是很好地工作。
对于您的问题,有一些类似于这样或这样的答案,它们基本上试图说明您需要编写自己的BatchConfigurer,而不是依赖于默认的BatchConfigurer。
使用Spring Boot,您应该尝试分离作业定义和作业执行。您应该首先尝试只定义作业并初始化Spring上下文,而不启用作业(Spring.batch.job.enabled=false
)
在Spring Boot main方法中,当您使用-SpringApplication.run(Application.class,args);
...启动应用程序时,您将得到ApplicationContext CTX
现在,您可以从这个上下文中获取相关的bean,通过从属性或命令行等获取名称来启动指定作业&使用joblauncher.run(...)
方法。
你可以参考我的这个答案,如果愿意订购的工作执行。您还可以使用Java编写作业调度程序。
重点是,您分离了作业构建/bean配置和作业执行的关注点。
挑战
是否可以在Spring批处理中动态配置作业? 这是我想做的。我创建了几个不同的,如下所示: FlatFileItemReader 我希望能够在创建批处理作业时动态混合和匹配它们。例如,假设我需要一个有2个步骤的作业。第一步包含一个用于预处理的。第二步将有一个,用于使用我的阅读器/写入器进行基于块的数据处理......类似这样的东西: 在XML中,我可以执行以下操作: 但是我如何像上面一样以编程方式
我们目前正在将一个复杂的spring boot batch+admin UI系统迁移到一个spring-cloud-task基础设施中,该基础设施将被管理云数据流。 作为POC的第一阶段,我们必须能够将所有Spring批处理作业打包在同一个部署JAR下,并且能够使用自定义作业参数一个接一个地运行它们,并且支持某种REST API远程执行作业/任务。 我们删除了所有spring-batch管理依赖项
到目前为止,我正在运行spring批处理,只有一个作业。现在我想运行多个不同的作业,这意味着不同的功能。在我的配置文件中,我配置了两个具有不同id和不同名称的作业。现在我得负责这些工作。你能告诉我怎么跑吗。在这里,我的疑问是在我的java类中,我已经为运行批处理编写了这段代码。 对于其他作业,如何调用jobLauncher的run方法。 我的配置文件是
我在BatchScheduler中有多个计划作业,它在特定时间运行。简单的内置JobLauncher,这是同步的。在自然界中最初使用。现在,我想并行运行这些作业,这样没有作业可以等待其他作业完成。 我在不同的作业上尝试过@Async注释,但都不起作用。 然后,我尝试设置joblauncher.settaskexecutor(新的SimpleAsyncTaskExecutor())。但这并不奏效。
我们正试图建立关于如何在大型IT服务中使用Spring Batch的标准,并具有不同的商业利益。 我们可能会有几个属于不同业务领域的批次。我们已经知道其中一些必须从所有批次通用的表中获取一些参数(即Java和COBOL;例如日期参数)。 我们将实现的Spring批处理作业的数量很难评估。没有重写现有COBOL批次的目标,只要有可能,就鼓励连续流程处理。 一些关于概念证明的问题不时出现,但目前几乎没
我正在使用Spring Boot+Spring Batch(注释),遇到了一个我必须运行2个作业的场景。 我有员工和工资记录,需要使用spring批处理更新。我已经按照本教程spring-batch入门教程为Employee和Salary对象配置了