-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Description
Bug description
I am developing an application that executes jobs by executing the TaskExecutorJobLauncher#run(job, jobParameters) method within a RESTful service.
The first time a job is executed, it works as expected.
However, when the job is executed the second time or later,
it is executed with the StepContribution instance and ChunkContext instance from the first execution passed to the tasklet (e.g. the jobInstanceId from the first execution is referenced from the second time or later).
The jobInstanceId value of JobListener and StepListener changes each time a job is executed.
After my investigation, I found that the cause was AbstractMethodInvokingDelegator.java and MethodInvokingTaskletAdapter.java.
https://github.com/spring-projects/spring-batch/blob/v5.2.2/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapter.java
There is a problem with the following code in MethodInvokingTaskletAdapter.java.
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
if (getArguments() == null) {
setArguments(new Object[] { contribution, chunkContext });
}
contribution.setExitStatus(mapResult(invokeDelegateMethod()));
return RepeatStatus.FINISHED;
}
getArguments() returns null for the first execution of a job, so getArguments() == null become true at the time.
When stepContribution and chunkContext are passed to MethodInvokingTaskletAdapter#execute,
setArguments is called in the first execution of a job, but MethodInvokingTaskletAdapter.arguments is not cleared to null after invokeDelegateMethod() is completed.
From the second job execution onwards, getArguments() no longer returns null, and the a stepContribution instance and a chunkContext instance of the first execution continues to be passed as two arguments to Tacklet#execute implementation.
Are there ways to resolve this issue? Please advise me.
By the way, it also seems that there is a problem with the current execute(StepContribution, ChunkContext) in MethodInvokingTaskletAdapter.java for me.
Shouldn't null be passed to the setArguments method immediately after executing invokeDelegateMethod() as follows to initialize the arguments field of MethodInvokingTaskletAdapter?
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
if (getArguments() == null) {
setArguments(new Object[] { contribution, chunkContext });
}
Object obj = null;
try {
obj = invokeDelegateMethod();
} finally {
setArguments(null);
}
contribution.setExitStatus(mapResult(obj));
return RepeatStatus.FINISHED;
}
As it stands now, there seems to be an issue where the first job's MethodInvokingTaskletAdapter.arguments continues to reference the instance, preventing it from being released by GC.
Because we need to proceed with development, as a workaround, we have temporarily changed the implementation to one where the StepExecution is temporarily added to a static Cache using the job name and step name as keys in StepListener#beforeStep,
and information equivalent to StepContext is obtained from the StepExecution instance temporarily pushed to Cache,
rather than using the information of chunkContext.getStepContext() passed to the execute method.
(The StepExecution is deleted from the static Cache immediately after the tasklet is executed.)
Environment
Please provide as many details as possible: Spring Batch version, Java version, which database you use if any, etc
Spring Framework version 6.2.5
Spring Batch version 5.2.2
Java version: 17.0.11 (Red_Hat-17.0.11.0+9-1)
Java Distribution: Red Hat build of OpenJDK
JEE AP Server: JBoss EAP 8.0 Update 4.1 (WildFly Core 21.0.11.Final-redhat-00001)
DataBase: Oracle DB express:21.3.0-xe
OS: Windows 11
Steps to reproduce
Steps to reproduce the issue.
Run a job once, then run the same job while changing the timestamp argument.
Expected behavior
A clear and concise description of what you expected to happen.
I would like Tacklet#execute to be passed stepContribution and chunkContext as arguments when each job is executed, just like JobListener and StepListener.
Minimal Complete Reproducible example
Please provide a failing test or a minimal complete verifiable example that reproduces the issue.
Bug reports that are reproducible will take priority in resolution over reports that are not reproducible.
I cannot reveal it at current time as it would violate our confidentiality.
However, if it is absolutely necessary, I will provide a sample app without any confidential information.
I'm sorry, it will take some long time.
Activity
Lavanyaproject1998 commentedon Apr 16, 2025
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
if (getArguments() == null) {
setArguments(new Object[] { contribution, chunkContext });
}
Object result = null;
try {
result = invokeDelegateMethod(); // Invoke delegate method
} finally {
setArguments(null); // Clear arguments after execution
}
contribution.setExitStatus(mapResult(result)); // Set exit status based on result
return RepeatStatus.FINISHED; // Mark the step as finished
}
You should modify the execute method to clear the arguments field after each execution. This will ensure that the StepContribution and ChunkContext from a previous execution aren't reused in subsequent executions
futokiyo commentedon Apr 16, 2025
Tasklet Implementation invoked by MethodInvokingTaskletAdapter is not able to modified.
Because a tasklet implementation is not able to access the arguments field of MethodInvokingTaskletAdapter.
Another candidate method is AbstractMethodInvokingDelegator#invokeDelegateMethod()
https://github.com/spring-projects/spring-batch/blob/v5.2.2/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/AbstractMethodInvokingDelegator.java
That can be modified as the following code( arguments = null; ).
fmbenhassine commentedon May 22, 2025
Can you please provide an example that reproduces the issue? I will debug the case to understand the problem. You can find a template with a starting project here: https://github.com/spring-projects/spring-batch/blob/main/ISSUE_REPORTING.md
futokiyo commentedon May 23, 2025
@fmbenhassine -san
Thank you for your reply.
I'm sorry, but I'm currently very busy with my work and my private personal matters and won't be able to respond right away.
I will adjust my tasks to make time. I would appreciate your patience until the end of July.
I will prepare a sample application for reproduction confirmation and the simple reproduction guide by referring to ISSUE_REPORTING.md.