Reputation: 953
I have a writer from which I have a dynamic value that needs to be passed to JobExecutionListener's afterJob(JobExecution jobExecution)
. Would appreciate some advice. Thank you.
<beans:bean>
<job id="GoodJob">
<step id="XXX"
allow-start-if-complete="true"
parent="XXX">
<tasklet transaction-manager="XXX">
<chunk reader="READER"
writer="WRITER"
commit-interval="100"/>
</tasklet>
</step>
<listener>
<beans:bean class="class that implements JobExecutionListener">
<beans:constructor-arg name="value"
value="DEFAULT IS FALSE DURING INITIALIZATION/MIGHT GET CHANGED IN WRITER, GET THIS VALUE FROM WRITER"/>
</beans:bean>
</listener>
</job>
</beans:beans>
Upvotes: 2
Views: 9397
Reputation: 33
I will add new information to what Mahmoud said. Now you have to add one extra step - promote ExecutionContext from Step to Job context if you want to get your data in JobListener.
@Bean
public ExecutionContextPromotionListener promotionListener() {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
listener.setKeys(new String[] {"data"});
return listener;
}
Than register it in your step.
@Bean
public Step step() {
return steps.get("step")
.<Integer, Integer>chunk(2)
.reader(itemReader())
.writer(itemWriter())
.listener(promotionListener())
.build();
}
Upvotes: 1
Reputation: 31730
You can pass data between these two components through the job execution context. This is detailed in the Passing Data to Future Steps section. Here is a quick example:
import java.util.Arrays;
import java.util.List;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableBatchProcessing
public class MyJob {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
public ItemReader<Integer> itemReader() {
return new ListItemReader<>(Arrays.asList(1, 2, 3, 4));
}
@Bean
public ItemWriter<Integer> itemWriter() {
return new ItemWriter<Integer>() {
private StepExecution stepExecution;
@Override
public void write(List<? extends Integer> items) throws Exception {
for (Integer item : items) {
System.out.println("item = " + item);
}
stepExecution.getJobExecution().getExecutionContext().put("data", "foo");
}
@BeforeStep
public void saveStepExecution(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
};
}
@Bean
public Step step() {
return steps.get("step")
.<Integer, Integer>chunk(2)
.reader(itemReader())
.writer(itemWriter())
.build();
}
@Bean
public Job job() {
return jobs.get("job")
.start(step())
.listener(new JobExecutionListener() {
@Override
public void beforeJob(JobExecution jobExecution) {
}
@Override
public void afterJob(JobExecution jobExecution) {
ExecutionContext executionContext = jobExecution.getExecutionContext();
String data = executionContext.getString("data");
System.out.println("data from writer = " + data);
}
})
.build();
}
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
jobLauncher.run(job, new JobParameters());
}
}
In this example, the writer writes the key data
with value foo
in the job execution context. Then, this key is retrieved from the execution context in the job listener.
Hope this helps.
Upvotes: 4