Java - Spring-Batch 和 Quartz 以及 Tomcat - 返回缓存的作业 bean 实例
Java - Spring-Batch and Quartz and Tomcat - Returning cached instance of job bean
我一直在尝试使用 Quartz 设置一个 Spring-批处理作业,所有 运行 都在 Tomcat 容器中。我使用来自 Whosebug 的许多帖子和各种文章使一切正常。
使用 Quartz 和 CronExpression,批处理作业设置为每分钟 运行。
现在的问题是实际的 Spring 批处理作业只有 运行 一次。这是一个成功的 运行,因为日志显示两个 classes 的输出:
2016-03-09 11:20:00,047 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 RunFirstBatch.run 111 : RunFirstBatch().run() - Starting.................................[]
2016-03-09 11:20:00,047 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 RunFirstBatch.run 112 : RunFirstBatch().run() - CWD......................................[C:\Users\n0002501\AppData\Local\CI Eclipse for Java EE]
...removed for brevity...
2016-03-09 11:20:03,880 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 FirstBatch.execute 113 : FirstBatch().execute().................................................[** First Batch Job is Executing! **]
2016-03-09 11:20:03,880 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 FirstBatch.execute 114 : FirstBatch().execute() Step Contribution...............................[[StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]]
2016-03-09 11:20:03,880 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 FirstBatch.execute 115 : FirstBatch().execute() Chunk Context...................................[ChunkContext: attributes=[], complete=false, stepContext=SynchronizedAttributeAccessor: [], stepExecutionContext={batch.stepType=org.springframework.batch.core.step.tasklet.TaskletStep, batch.taskletType=com.lmig.batch.FirstBatch}, jobExecutionContext={}, jobParameters={}]
...removed for brevity...
2016-03-09 11:20:05,542 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 SimpleJobLauncher.run 136 : Job: [FlowJob: [name=firstBatchJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2016-03-09 11:20:05,542 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 RunFirstBatch.run 126 : RunFirstBatch().run() - Exit Status..............................[COMPLETED]
2016-03-09 11:20:05,542 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 RunFirstBatch.run 145 : RunFirstBatch().run()............................................[finally]
问题出在所有后续 运行 上,Spring returns 批处理作业的缓存实例 class 而不是 运行 它表明它处于完成状态:
2016-03-09 11:21:00,008 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 RunFirstBatch.run 111 : RunFirstBatch().run() - Starting.................................[]
2016-03-09 11:21:00,008 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 RunFirstBatch.run 112 : RunFirstBatch().run() - CWD......................................[C:\Users\n0002501\AppData\Local\CI Eclipse for Java EE]
...removed for brevity...
...Returning cached instance of singleton bean 'firstBatchJob'
...removed for brevity...
2016-03-09 11:21:01,730 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleStepHandler.shouldStart 217 : Step already complete or not restartable, so no action to execute: StepExecution: id=1, version=3, name=stepOne, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2016-03-09 11:21:01,730 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleFlow.resume 178 : Completed state=firstBatchJob.stepOne with status=COMPLETED
2016-03-09 11:21:01,730 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleFlow.resume 164 : Handling state=firstBatchJob.end1
2016-03-09 11:21:01,730 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleFlow.resume 178 : Completed state=firstBatchJob.end1 with status=COMPLETED
2016-03-09 11:21:01,730 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 AbstractJob.execute 305 : Job execution complete: JobExecution: id=1, version=1, startTime=Wed Mar 09 11:21:00 EST 2016, endTime=null, lastUpdated=Wed Mar 09 11:21:00 EST 2016, status=COMPLETED, exitStatus=exitCode=COMPLETED;exitDescription=, job=[JobInstance: id=0, version=0, Job=[firstBatchJob]], jobParameters=[{}]
...removed for brevity...
2016-03-09 11:21:02,050 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleJobLauncher.run 136 : Job: [FlowJob: [name=firstBatchJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2016-03-09 11:21:02,050 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 RunFirstBatch.run 126 : RunFirstBatch().run() - Exit Status..............................[COMPLETED]
2016-03-09 11:21:02,050 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 RunFirstBatch.run 145 : RunFirstBatch().run()............................................[finally]
我尝试过的事情:
- 范围="prototype"
- 可重启="true"
- 实施 ApplicationContextAware class 以获取 ApplicationContext。
- 为 beforeJob() 和 afterJob() 实现了 JobExecutionListener class。
详情如下:
<bean id="batchApplicationContext" class="com.lmig.cm.rore.refmigrator.BatchApplicationContextProvider" scope="singleton"/>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher" scope="prototype">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="firstBatch" class="com.lmig.batch.FirstBatch" scope="prototype"/>
<batch:step id="firstBatchStepOne">
<batch:tasklet ref="firstBatch"/>
</batch:step>
<batch:job id="firstBatchJob" restartable="true">
<batch:step id="stepOne" parent="firstBatchStepOne"/>
</batch:job>
<bean id="runFirstBatch" class="com.lmig.cm.rore.refmigrator.RunFirstBatch">
<property name="context" ref="batchApplicationContext" />
</bean>
RunFirstBatch class :
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
public class RunFirstBatch {
public static final String ID = RunFirstBatch.class.getName ();
private String SHORT_NAME = "RunFirstBatch()";
@SuppressWarnings("unused")
private String SYSTEM_IDENTITY = String.valueOf ( System.identityHashCode ( this ) );
private Log log = LogFactory.getLog(RunFirstBatch.class.getName());
//private ApplicationContext context = null;
private BatchApplicationContextProvider context;
/**
* Default constructor.
*/
public RunFirstBatch() {
this.context = new BatchApplicationContextProvider();
}
public void run() {
try {
getLog().info ( SHORT_NAME + ".run() - Starting.................................[" + "]" );
getLog().info ( SHORT_NAME + ".run() - CWD......................................[" + System.getProperty ( "user.dir" ) + "]" );
//context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
//this.context = new ClassPathXmlApplicationContext("/RoreWebConfiguration.xml");
//String[] springConfig = {"/first-batch.xml"};
//context = new ClassPathXmlApplicationContext ( springConfig );
if ( getContext() != null ) {
if ( getContext().getApplicationContext () != null ) {
JobLauncher jobLauncher = (JobLauncher)getContext().getApplicationContext ().getBean("jobLauncher");
Job job = (Job) getContext().getApplicationContext ().getBean("firstBatchJob");
JobExecution execution = jobLauncher.run ( job, new JobParameters() );
//jobLauncher.run ( job, new JobParameters() );
getLog().info ( SHORT_NAME + ".run() - Exit Status..............................[" + execution.getStatus () + "]" );
}
else {
getLog().info ( SHORT_NAME + ".run() - ApplicationContext is NULL...............[NULL]" );
}
}
else {
getLog().info ( SHORT_NAME + ".run() - BatchApplicationContext is NULL..........[NULL]" );
}
}
catch ( Exception ltheXcp ) {
getLog().error ( SHORT_NAME + ".run() - Exception ...............................[" + ltheXcp.getMessage () + "]" );
getLog().error ( ltheXcp );
}
finally {
getLog().info ( SHORT_NAME + ".run()............................................[finally]" );
//if (context != null) {
// context = null;
//}
}
}
public Log getLog() {
return log;
}
public void setLog(Log log) {
this.log = log;
}
public BatchApplicationContextProvider getContext() {
return context;
}
public void setContext(BatchApplicationContextProvider context) {
this.context = context;
}
}
第一批class:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import com.lmig.cm.rore.refmigrator.CMRoreReferenceMigrator;
public class FirstBatch implements Tasklet {
public static final String ID = FirstBatch.class.getName ();
private String SHORT_NAME = "FirstBatch()";
@SuppressWarnings("unused")
private String SYSTEM_IDENTITY = String.valueOf ( System.identityHashCode ( this ) );
private Log log = LogFactory.getLog(FirstBatch.class.getName());
public FirstBatch() {
// TODO Auto-generated constructor stub
}
public FirstBatch( Log theLog ) {
this.log = theLog;
}
/* (non-Javadoc)
* @see org.springframework.batch.core.step.tasklet.Tasklet#execute(org.springframework.batch.core.StepContribution, org.springframework.batch.core.scope.context.ChunkContext)
*/
@Override
public RepeatStatus execute(StepContribution arg0, ChunkContext arg1)
throws Exception {
getLog().info(SHORT_NAME + ".execute().................................................[** First Batch Job is Executing! **]");
getLog().info(SHORT_NAME + ".execute() Step Contribution...............................[" + arg0.toString () + "]");
getLog().info(SHORT_NAME + ".execute() Chunk Context...................................[" + arg1.toString () + "]");
return RepeatStatus.FINISHED;
//return RepeatStatus.CONTINUABLE;
}
public Log getLog() {
return log;
}
public void setLog(Log log) {
this.log = log;
}
}
我怀疑这很简单,但我似乎找不到正确的设置、属性或选项来让它重新开始工作。
提前谢谢,
阿迪姆
Michael 回答的解决方案:
- Spring 批处理 3.0.2
- JDK 1.7-79
- Spring 3.2.14
- 石英 2.2.2
- Tomcat 6.0.44
解决方案是在 JobParameters() 中简单地提供至少 1 个 JobParameter,它允许 Spring-Batch "uniquely" 识别一个 JobInstance 与另一个。我只是将当前 Date/Time 用作字符串:
在 RunFirstBatch.run() 方法中添加以下代码:
SimpleDateFormat theFormat = new SimpleDateFormat ( "yyyy-MM-dd-HH-mm-ss" );
if ( getBatchContext ().getApplicationContext () != null ) {
if ( getBatchContext ().getApplicationContext () != null ) {
JobLauncher jobLauncher = (JobLauncher)getBatchContext ().getApplicationContext ().getBean("jobLauncher");
Job job = (Job) getBatchContext ().getApplicationContext ().getBean("firstBatchJob");
// JOBPARAMETERS : Build the job parameters...
//
Date theDate = new Date();
// format the date as yyyy-MM-dd-HH-mm-ss
String theJobId = theFormat.format ( theDate );
// job parameter (single) from the formatted date...
JobParameter idParm = new JobParameter ( theJobId );
// parameters container...used for the JobParameters
// constructor...
Map<String,JobParameter> mapParms = new HashMap<String,JobParameter> ();
mapParms.put ( "1", idParm );
JobParameters theParms = new JobParameters (mapParms);
getLog().info ( SHORT_NAME + ".run() - Job Id...................................[" + theJobId + "]" );
JobExecution execution = jobLauncher.run ( job, theParms );
//execution.setExitStatus ( ExitStatus.UNKNOWN );
//jobLauncher.run ( job, new JobParameters() );
getLog().info ( SHORT_NAME + ".run() - Exit Status..............................[" + execution.getStatus () + "]" );
}
else {
getLog().info ( SHORT_NAME + ".run() - ApplicationContext is NULL...............[NULL]" );
}
}
else {
getLog().info ( SHORT_NAME + ".run() - BatchApplicationContext is NULL..........[NULL]" );
}
保留 RepeatStatus.FINISHED 但查看 https://docs.spring.io/spring-batch/reference/html/domain.html#domainJobParameters
"how is one JobInstance distinguished from another?" The answer is:
JobParameters. JobParameters is a set of parameters used to start a
batch job.
和
Thus, the contract can be defined as: JobInstance = Job + identifying
JobParameters. This allows a developer to effectively control how a
JobInstance is defined, since they control what parameters are passed
in.
...所以考虑一个识别作业参数(随机的,唯一的,也许 Date.getTime())?
我一直在尝试使用 Quartz 设置一个 Spring-批处理作业,所有 运行 都在 Tomcat 容器中。我使用来自 Whosebug 的许多帖子和各种文章使一切正常。
使用 Quartz 和 CronExpression,批处理作业设置为每分钟 运行。
现在的问题是实际的 Spring 批处理作业只有 运行 一次。这是一个成功的 运行,因为日志显示两个 classes 的输出:
2016-03-09 11:20:00,047 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 RunFirstBatch.run 111 : RunFirstBatch().run() - Starting.................................[]
2016-03-09 11:20:00,047 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 RunFirstBatch.run 112 : RunFirstBatch().run() - CWD......................................[C:\Users\n0002501\AppData\Local\CI Eclipse for Java EE]
...removed for brevity...
2016-03-09 11:20:03,880 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 FirstBatch.execute 113 : FirstBatch().execute().................................................[** First Batch Job is Executing! **]
2016-03-09 11:20:03,880 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 FirstBatch.execute 114 : FirstBatch().execute() Step Contribution...............................[[StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]]
2016-03-09 11:20:03,880 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 FirstBatch.execute 115 : FirstBatch().execute() Chunk Context...................................[ChunkContext: attributes=[], complete=false, stepContext=SynchronizedAttributeAccessor: [], stepExecutionContext={batch.stepType=org.springframework.batch.core.step.tasklet.TaskletStep, batch.taskletType=com.lmig.batch.FirstBatch}, jobExecutionContext={}, jobParameters={}]
...removed for brevity...
2016-03-09 11:20:05,542 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 SimpleJobLauncher.run 136 : Job: [FlowJob: [name=firstBatchJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2016-03-09 11:20:05,542 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 RunFirstBatch.run 126 : RunFirstBatch().run() - Exit Status..............................[COMPLETED]
2016-03-09 11:20:05,542 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1 RunFirstBatch.run 145 : RunFirstBatch().run()............................................[finally]
问题出在所有后续 运行 上,Spring returns 批处理作业的缓存实例 class 而不是 运行 它表明它处于完成状态:
2016-03-09 11:21:00,008 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 RunFirstBatch.run 111 : RunFirstBatch().run() - Starting.................................[]
2016-03-09 11:21:00,008 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 RunFirstBatch.run 112 : RunFirstBatch().run() - CWD......................................[C:\Users\n0002501\AppData\Local\CI Eclipse for Java EE]
...removed for brevity...
...Returning cached instance of singleton bean 'firstBatchJob'
...removed for brevity...
2016-03-09 11:21:01,730 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleStepHandler.shouldStart 217 : Step already complete or not restartable, so no action to execute: StepExecution: id=1, version=3, name=stepOne, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2016-03-09 11:21:01,730 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleFlow.resume 178 : Completed state=firstBatchJob.stepOne with status=COMPLETED
2016-03-09 11:21:01,730 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleFlow.resume 164 : Handling state=firstBatchJob.end1
2016-03-09 11:21:01,730 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleFlow.resume 178 : Completed state=firstBatchJob.end1 with status=COMPLETED
2016-03-09 11:21:01,730 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 AbstractJob.execute 305 : Job execution complete: JobExecution: id=1, version=1, startTime=Wed Mar 09 11:21:00 EST 2016, endTime=null, lastUpdated=Wed Mar 09 11:21:00 EST 2016, status=COMPLETED, exitStatus=exitCode=COMPLETED;exitDescription=, job=[JobInstance: id=0, version=0, Job=[firstBatchJob]], jobParameters=[{}]
...removed for brevity...
2016-03-09 11:21:02,050 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 SimpleJobLauncher.run 136 : Job: [FlowJob: [name=firstBatchJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
2016-03-09 11:21:02,050 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 RunFirstBatch.run 126 : RunFirstBatch().run() - Exit Status..............................[COMPLETED]
2016-03-09 11:21:02,050 INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 RunFirstBatch.run 145 : RunFirstBatch().run()............................................[finally]
我尝试过的事情:
- 范围="prototype"
- 可重启="true"
- 实施 ApplicationContextAware class 以获取 ApplicationContext。
- 为 beforeJob() 和 afterJob() 实现了 JobExecutionListener class。
详情如下:
<bean id="batchApplicationContext" class="com.lmig.cm.rore.refmigrator.BatchApplicationContextProvider" scope="singleton"/>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher" scope="prototype">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="firstBatch" class="com.lmig.batch.FirstBatch" scope="prototype"/>
<batch:step id="firstBatchStepOne">
<batch:tasklet ref="firstBatch"/>
</batch:step>
<batch:job id="firstBatchJob" restartable="true">
<batch:step id="stepOne" parent="firstBatchStepOne"/>
</batch:job>
<bean id="runFirstBatch" class="com.lmig.cm.rore.refmigrator.RunFirstBatch">
<property name="context" ref="batchApplicationContext" />
</bean>
RunFirstBatch class :
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
public class RunFirstBatch {
public static final String ID = RunFirstBatch.class.getName ();
private String SHORT_NAME = "RunFirstBatch()";
@SuppressWarnings("unused")
private String SYSTEM_IDENTITY = String.valueOf ( System.identityHashCode ( this ) );
private Log log = LogFactory.getLog(RunFirstBatch.class.getName());
//private ApplicationContext context = null;
private BatchApplicationContextProvider context;
/**
* Default constructor.
*/
public RunFirstBatch() {
this.context = new BatchApplicationContextProvider();
}
public void run() {
try {
getLog().info ( SHORT_NAME + ".run() - Starting.................................[" + "]" );
getLog().info ( SHORT_NAME + ".run() - CWD......................................[" + System.getProperty ( "user.dir" ) + "]" );
//context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
//this.context = new ClassPathXmlApplicationContext("/RoreWebConfiguration.xml");
//String[] springConfig = {"/first-batch.xml"};
//context = new ClassPathXmlApplicationContext ( springConfig );
if ( getContext() != null ) {
if ( getContext().getApplicationContext () != null ) {
JobLauncher jobLauncher = (JobLauncher)getContext().getApplicationContext ().getBean("jobLauncher");
Job job = (Job) getContext().getApplicationContext ().getBean("firstBatchJob");
JobExecution execution = jobLauncher.run ( job, new JobParameters() );
//jobLauncher.run ( job, new JobParameters() );
getLog().info ( SHORT_NAME + ".run() - Exit Status..............................[" + execution.getStatus () + "]" );
}
else {
getLog().info ( SHORT_NAME + ".run() - ApplicationContext is NULL...............[NULL]" );
}
}
else {
getLog().info ( SHORT_NAME + ".run() - BatchApplicationContext is NULL..........[NULL]" );
}
}
catch ( Exception ltheXcp ) {
getLog().error ( SHORT_NAME + ".run() - Exception ...............................[" + ltheXcp.getMessage () + "]" );
getLog().error ( ltheXcp );
}
finally {
getLog().info ( SHORT_NAME + ".run()............................................[finally]" );
//if (context != null) {
// context = null;
//}
}
}
public Log getLog() {
return log;
}
public void setLog(Log log) {
this.log = log;
}
public BatchApplicationContextProvider getContext() {
return context;
}
public void setContext(BatchApplicationContextProvider context) {
this.context = context;
}
}
第一批class:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import com.lmig.cm.rore.refmigrator.CMRoreReferenceMigrator;
public class FirstBatch implements Tasklet {
public static final String ID = FirstBatch.class.getName ();
private String SHORT_NAME = "FirstBatch()";
@SuppressWarnings("unused")
private String SYSTEM_IDENTITY = String.valueOf ( System.identityHashCode ( this ) );
private Log log = LogFactory.getLog(FirstBatch.class.getName());
public FirstBatch() {
// TODO Auto-generated constructor stub
}
public FirstBatch( Log theLog ) {
this.log = theLog;
}
/* (non-Javadoc)
* @see org.springframework.batch.core.step.tasklet.Tasklet#execute(org.springframework.batch.core.StepContribution, org.springframework.batch.core.scope.context.ChunkContext)
*/
@Override
public RepeatStatus execute(StepContribution arg0, ChunkContext arg1)
throws Exception {
getLog().info(SHORT_NAME + ".execute().................................................[** First Batch Job is Executing! **]");
getLog().info(SHORT_NAME + ".execute() Step Contribution...............................[" + arg0.toString () + "]");
getLog().info(SHORT_NAME + ".execute() Chunk Context...................................[" + arg1.toString () + "]");
return RepeatStatus.FINISHED;
//return RepeatStatus.CONTINUABLE;
}
public Log getLog() {
return log;
}
public void setLog(Log log) {
this.log = log;
}
}
我怀疑这很简单,但我似乎找不到正确的设置、属性或选项来让它重新开始工作。
提前谢谢, 阿迪姆
Michael 回答的解决方案:
- Spring 批处理 3.0.2
- JDK 1.7-79
- Spring 3.2.14
- 石英 2.2.2
- Tomcat 6.0.44
解决方案是在 JobParameters() 中简单地提供至少 1 个 JobParameter,它允许 Spring-Batch "uniquely" 识别一个 JobInstance 与另一个。我只是将当前 Date/Time 用作字符串:
在 RunFirstBatch.run() 方法中添加以下代码:
SimpleDateFormat theFormat = new SimpleDateFormat ( "yyyy-MM-dd-HH-mm-ss" );
if ( getBatchContext ().getApplicationContext () != null ) {
if ( getBatchContext ().getApplicationContext () != null ) {
JobLauncher jobLauncher = (JobLauncher)getBatchContext ().getApplicationContext ().getBean("jobLauncher");
Job job = (Job) getBatchContext ().getApplicationContext ().getBean("firstBatchJob");
// JOBPARAMETERS : Build the job parameters...
//
Date theDate = new Date();
// format the date as yyyy-MM-dd-HH-mm-ss
String theJobId = theFormat.format ( theDate );
// job parameter (single) from the formatted date...
JobParameter idParm = new JobParameter ( theJobId );
// parameters container...used for the JobParameters
// constructor...
Map<String,JobParameter> mapParms = new HashMap<String,JobParameter> ();
mapParms.put ( "1", idParm );
JobParameters theParms = new JobParameters (mapParms);
getLog().info ( SHORT_NAME + ".run() - Job Id...................................[" + theJobId + "]" );
JobExecution execution = jobLauncher.run ( job, theParms );
//execution.setExitStatus ( ExitStatus.UNKNOWN );
//jobLauncher.run ( job, new JobParameters() );
getLog().info ( SHORT_NAME + ".run() - Exit Status..............................[" + execution.getStatus () + "]" );
}
else {
getLog().info ( SHORT_NAME + ".run() - ApplicationContext is NULL...............[NULL]" );
}
}
else {
getLog().info ( SHORT_NAME + ".run() - BatchApplicationContext is NULL..........[NULL]" );
}
保留 RepeatStatus.FINISHED 但查看 https://docs.spring.io/spring-batch/reference/html/domain.html#domainJobParameters
"how is one JobInstance distinguished from another?" The answer is: JobParameters. JobParameters is a set of parameters used to start a batch job.
和
Thus, the contract can be defined as: JobInstance = Job + identifying JobParameters. This allows a developer to effectively control how a JobInstance is defined, since they control what parameters are passed in.
...所以考虑一个识别作业参数(随机的,唯一的,也许 Date.getTime())?