Skip to content

Incorrect step configuration when setting the taskExecutor before faultTolerant() #4438

Closed
@Wood-Chopper

Description

@Wood-Chopper

Hello,

I think I spotted an issue related to the StepBuilder. Depending on the order a developer build its step, the taskExecutor field will have different values.

Here is a minimal example to reproduce the issue:

step1 and step2 are exactly the same, except in one thing.

public class SpringBatchTest {

    private PlatformTransactionManager transactionManager = mock(PlatformTransactionManager.class);
    private JobRepository jobRepository =  mock(JobRepository.class);
    private ItemReader itemReader = mock(ItemReader.class);
    private ItemProcessor itemProcessor = mock(ItemProcessor.class);
    private ItemWriter itemWriter = mock(ItemWriter.class);

    private SimpleAsyncTaskExecutor taskExecutor  = new SimpleAsyncTaskExecutor();

    @Test
    void test_inconsistent_behavior() {
        TaskletStep step1 = new StepBuilder("step-name", jobRepository)
                .chunk(10, transactionManager)
                .reader(itemReader)
                .processor(itemProcessor)
                .writer(itemWriter)
                .faultTolerant()
                .taskExecutor(taskExecutor)
                .build();
        TaskletStep step2 = new StepBuilder("step-name", jobRepository)
                .chunk(10, transactionManager)
                .taskExecutor(taskExecutor)// The task executor is set before faultTolerant()
                .reader(itemReader)
                .processor(itemProcessor)
                .writer(itemWriter)
                .faultTolerant()
                .build();

        RepeatTemplate stepOperations1 = (RepeatTemplate) ReflectionUtils
                .readFieldValue(TaskletStep.class, "stepOperations", step1).get();// TaskExecutorRepeatTemplate
        RepeatTemplate stepOperations2 = (RepeatTemplate) ReflectionUtils
                .readFieldValue(TaskletStep.class, "stepOperations", step2).get();// RepeatTemplate

        assertEquals(stepOperations1.getClass(), stepOperations2.getClass());// This fails
    }
}

In this example, step2 will use the default task executor instead of the provided one.

Looking at the code, the taskExecutor value is lost after setting faultTolerant().

I did not go too deep into the solution, but I think the issue comes from this constructor (see link). The taskExecutor value could be kept from there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    for: backport-to-5.0.xIssues that will be back-ported to the 5.0.x linefor: backport-to-5.1.xIssues that will be back-ported to the 5.1.x linehas: minimal-exampleBug reports that provide a minimal complete reproducible examplein: coretype: bug

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions