How do I get Spring Batch Job ContextId in ItemProcessor or ItemWriter?
Asked Answered
W

7

12

I need to store Job ExecutionId as one of the fields of Entity. (I am using JpaItemWriter) One of topic here explains from StepExcecution, I can get StepContext -> JobExecution. In that case how to get StepExecution?

(I have no need to pass any data from one step to another, all I need is JobExecuionId)

Thanks for help, Muneer Ahmed

Weingartner answered 10/1, 2013 at 17:20 Comment(0)
F
7

I would suggest you use a processor that updates your Entity with value. If your processors directly implements ItemProcessor<T> then you will not automatically get the StepExecution. To get the StepExecution, do 1 of the following; - implement StepExecutionListener and set it as a variable from the beforeStep method - create a method called [something](StepExecution execution) and annotate with @BeforeStep

once you've injected the StepExecution via a listener, you can then get the jobExecutionId and set it into your entity

public class MyEntityProcessor implements ItemProcessor<MyEntity, MyEntity> {

private long jobExecutionId;

@BeforeStep
public void beforeStep(StepExecution stepExecution) {
    jobExecutionId = stepExecution.getJobExecutionId();
}

@Override
public MyEntity process(MyEntity item) throws Exception {
    //set the values
    item.setJobExecutionId(jobExecutionId);
    //continue
    return item;
}

}
Farinaceous answered 10/1, 2013 at 17:49 Comment(4)
It is "complete code" contrary to your name ;-) . Thanks for your answer. Great help.Weingartner
could you post the spring context xml used to wire this bean. I'm following the same pattern but it seems the beforeStep() is not being called. Do you need to explicity register the MyEntityProcessor bean as a listener somewhere?Shingly
I used this solution for this problem and it worked, but it turns out it is not thread safe. If you multiple jobs running they can get the wrong job id which is a serious problem.Stagey
You have to set this processor as a listener... so for me this solution doesn't smell well... Better set it in another class who is dedicated to this purposeForeign
K
5

We can set the scope as job using @Scope("job") of Itemprocessor and can easly get JobExecution using @Value("#{jobExecution}") expression as below.

@Service
@Scope("job")
public class XsltTransformer implements ItemProcessor<Record, Record> {

@Value("#{jobExecution}")
private JobExecution jobExecution;

}
Kuska answered 8/10, 2015 at 12:48 Comment(1)
I ran into issues with this because the scope of a item processor is "step". Instead I retrieved the stepExecution and got the job execution by calling stepExecution.getJobExecution().Hortatory
L
4

You have to add the following:

@Value("#{stepExecution.jobExecution}")

private JobExecution jobExecution;

in your reader Writer or processor. It will certainly work.

Launder answered 24/10, 2018 at 10:45 Comment(0)
F
3

Scope as job using @Scope("job") of and get JobExecution using @Value("#{jobExecution}")

Frowzy answered 13/1, 2017 at 7:1 Comment(0)
D
1

If you want to use @BeforeStep in MyEntityProcessor you must declare it like a listener

<batch:listeners>
 <batch:listener ref="myEntityProcessor" />
</batch:listeners>
Drawback answered 10/3, 2015 at 11:52 Comment(0)
P
1

I had same issue. I used @StepScope in my processor Implementation

@Value("#{stepExecution.jobExecution}")
private JobExecution jobExecution;
Predominant answered 16/5, 2023 at 9:55 Comment(0)
H
0

I had a similar issue when I wanted to get the JobInstanceID. Below is how I got StepExecution and then retreived JobExecution. I hope this helps.

public class FoobarItemProcessor implements ItemProcessor<Foobar, Foobar> {

private JobExecution jobExecution;

@BeforeStep
public void beforeStep(StepExecution stepExecution) {
    jobExecution = stepExecution.getJobExecution();
}
Hortatory answered 11/11, 2016 at 15:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.