我正在尝试在Spring Batch 2中启动一个作业,我需要在作业参数中传递一些信息,但我不希望它计算作业实例的唯一性。例如,我希望这两组参数被认为是唯一的:
file=/my/file/path,session=1234
file=/my/file/path,session=5678
这个想法是,将有两个不同的服务器尝试启动相同的工作,但附加了不同的会话。在这两种情况下我都需要那个会话号码。有什么想法吗?
谢谢!
答案 0 :(得分:4)
因此,如果'file'是唯一一个应该是唯一的属性,并且'session'被下游代码使用,那么你的问题几乎与我所拥有的相匹配。我有一个JMSCorrelationId,我需要存储在执行上下文中供以后使用,我不希望它发挥作业参数的唯一性。 Per Dave Syer,这真的不可能,所以我采用了参数创建工作的路径(在你的情况下不是'session'),然后在任何实际运行之前将'session'属性添加到执行上下文中
这使我能够访问下游的'session',但它不在作业参数中,所以它不会影响唯一性。
https://jira.springsource.org/browse/BATCH-1412
http://forum.springsource.org/showthread.php?104440-Non-Identity-Job-Parameters&highlight=
你会从这个论坛上看到没有好办法(根据Dave Syer),但是我根据SimpleJobLauncher编写了自己的启动器(事实上,如果调用非重载方法,我会委托给SimpleLauncher )它有一个重载的方法来启动一个带有回调接口的作业,该接口允许将参数贡献给执行上下文而不是'true'作业参数。你可以做一些非常相似的事情。
我认为您的适用LOC就在这里: jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);
if (contributor != null) {
if (contributor.contributeTo(jobExecution.getExecutionContext())) {
jobRepository.updateExecutionContext(jobExecution);
}
}
这是在执行上下文creatin之后添加执行上下文的地方。希望这有助于您实施。
public class ControlMJobLauncher implements JobLauncher, InitializingBean {
private JobRepository jobRepository;
private TaskExecutor taskExecutor;
private SimpleJobLauncher simpleLauncher;
private JobFilter jobFilter;
public void setJobRepository(JobRepository jobRepository) {
this.jobRepository = jobRepository;
}
public void setTaskExecutor(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
/**
* Optional filter to prevent job launching based on some specific criteria.
* Jobs that are filtered out will return success to ControlM, but will not run
*/
public void setJobFilter(JobFilter jobFilter) {
this.jobFilter = jobFilter;
}
public JobExecution run(final Job job, final JobParameters jobParameters, ExecutionContextContributor contributor)
throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException, JobFilteredException {
Assert.notNull(job, "The Job must not be null.");
Assert.notNull(jobParameters, "The JobParameters must not be null.");
//See if job is filtered
if(this.jobFilter != null && !jobFilter.launchJob(job, jobParameters)) {
throw new JobFilteredException(String.format("Job has been filtered by the filter: %s", jobFilter.getFilterName()));
}
final JobExecution jobExecution;
JobExecution lastExecution = jobRepository.getLastJobExecution(job.getName(), jobParameters);
if (lastExecution != null) {
if (!job.isRestartable()) {
throw new JobRestartException("JobInstance already exists and is not restartable");
}
logger.info(String.format("Restarting job %s instance %d", job.getName(), lastExecution.getId()));
}
// Check the validity of the parameters before doing creating anything
// in the repository...
job.getJobParametersValidator().validate(jobParameters);
/*
* There is a very small probability that a non-restartable job can be
* restarted, but only if another process or thread manages to launch
* <i>and</i> fail a job execution for this instance between the last
* assertion and the next method returning successfully.
*/
jobExecution = jobRepository.createJobExecution(job.getName(),
jobParameters);
if (contributor != null) {
if (contributor.contributeTo(jobExecution.getExecutionContext())) {
jobRepository.updateExecutionContext(jobExecution);
}
}
try {
taskExecutor.execute(new Runnable() {
public void run() {
try {
logger.info("Job: [" + job
+ "] launched with the following parameters: ["
+ jobParameters + "]");
job.execute(jobExecution);
logger.info("Job: ["
+ job
+ "] completed with the following parameters: ["
+ jobParameters
+ "] and the following status: ["
+ jobExecution.getStatus() + "]");
} catch (Throwable t) {
logger.warn(
"Job: ["
+ job
+ "] failed unexpectedly and fatally with the following parameters: ["
+ jobParameters + "]", t);
rethrow(t);
}
}
private void rethrow(Throwable t) {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else if (t instanceof Error) {
throw (Error) t;
}
throw new IllegalStateException(t);
}
});
} catch (TaskRejectedException e) {
jobExecution.upgradeStatus(BatchStatus.FAILED);
if (jobExecution.getExitStatus().equals(ExitStatus.UNKNOWN)) {
jobExecution.setExitStatus(ExitStatus.FAILED
.addExitDescription(e));
}
jobRepository.update(jobExecution);
}
return jobExecution;
}
static interface ExecutionContextContributor {
boolean CONTRIBUTED_SOMETHING = true;
boolean CONTRIBUTED_NOTHING = false;
/**
*
* @param executionContext
* @return true if the exeuctioncontext was contributed to
*/
public boolean contributeTo(ExecutionContext executionContext);
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.state(jobRepository != null, "A JobRepository has not been set.");
if (taskExecutor == null) {
logger.info("No TaskExecutor has been set, defaulting to synchronous executor.");
taskExecutor = new SyncTaskExecutor();
}
this.simpleLauncher = new SimpleJobLauncher();
this.simpleLauncher.setJobRepository(jobRepository);
this.simpleLauncher.setTaskExecutor(taskExecutor);
this.simpleLauncher.afterPropertiesSet();
}
@Override
public JobExecution run(Job job, JobParameters jobParameters)
throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
return simpleLauncher.run(job, jobParameters);
}
}
答案 1 :(得分:3)
从春季批次2.2.x开始,支持非标识参数。如果您使用的是CommandLineJobRunner,则可以使用“ - ”前缀指定非标识参数。 例如: java org.springframework.batch.core.launch.support.CommandLineJobRunner file = / my / file / path -session = 5678
如果您使用的是旧版本的spring批处理,则需要迁移数据库架构。请参阅http://docs.spring.io/spring-batch/getting-started.html处的“迁移到2.x.x”部分。
这是功能https://jira.springsource.org/browse/BATCH-1412的Jira页面,以下是实现它的更改https://fisheye.springsource.org/changelog/spring-batch?cs=557515df45c0f596588418d53c3f2bae3781c1c3