How to access execution context from a Spring Batch Step? Error: No context holder available for job scope

user14486146

I am trying to set the chunk size of my spring batch job at runtime by injecting it into my step as follows:

@Bean
@JobScope
@Qualifier("myStep")
public Step myStep(@Value("#{jobExecutionContext['chunkSize']}") Integer chunkSize, StepBuilderFactory stepBuilderFactory, ItemReader<Object> reader, ItemWriter<Object> writer, Listener listener) {
    return stepBuilderFactory.get("myStep")
    .<Object, Object>chunk(chunkSize)
    .reader(reader)
    .writer(writer)
    .listener(listener)
    .build();
}

But I am getting the following error: java.lang.IllegalStateException: No context holder available for job scope

I've done some research online but am not able to understand why I am hitting this exception. I'd appreciate assistance in understanding what this error means and how to resolve it. Thanks!

Mahmoud Ben Hassine

I have the chunk sizes defined in a database table for each job that needs to get run. The chunk size gets put into the execution context through a tasklet that runs before this step in the job

Here is a quick example which works as expected:

import java.util.Arrays;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.listener.ChunkListenerSupport;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Value;
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 SO64447747WithJobExecutionContext {

    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory.get("step1")
                .tasklet((contribution, chunkContext) -> {
                    // TODO get chunk size from table and put in job execution context
                    chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put("chunkSize", 2);
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    @JobScope
    public Step step2(StepBuilderFactory stepBuilderFactory, @Value("#{jobExecutionContext['chunkSize']}") Integer chunkSize) {
        return stepBuilderFactory.get("step2")
                .<Integer, Integer>chunk(chunkSize)
                .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4)))
                .writer(items -> items.forEach(System.out::println))
                .listener(new ChunkListenerSupport() {
                    @Override
                    public void beforeChunk(ChunkContext context) {
                        System.out.println("starting to work on a new chunk of size " + chunkSize);
                    }
                })
                .build();
    }

    @Bean
    public Job job(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
        return jobBuilderFactory.get("job")
                .start(step1(stepBuilderFactory))
                .next(step2(stepBuilderFactory, null))
                .build();
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(SO64447747WithJobExecutionContext.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        jobLauncher.run(job, new JobParameters());
    }

}

This prints the following output without the error you mentioned:

starting to work on a new chunk of size 2
1
2
starting to work on a new chunk of size 2
3
4

I tried to pass the chunk size as a job parameter but I see the same issue regarding the job scope.

The same approach works without any exception when passing the chunkSize as a job parameter:

import java.util.Arrays;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.listener.ChunkListenerSupport;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Value;
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 SO64447747WithJobParameter {

    @Bean
    @JobScope
    public Step step(StepBuilderFactory stepBuilderFactory, @Value("#{jobParameters['chunkSize']}") Integer chunkSize) {
        return stepBuilderFactory.get("step")
                .<Integer, Integer>chunk(chunkSize)
                .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4)))
                .writer(items -> items.forEach(System.out::println))
                .listener(new ChunkListenerSupport() {
                    @Override
                    public void beforeChunk(ChunkContext context) {
                        System.out.println("starting to work on a new chunk of size " + chunkSize);
                    }
                })
                .build();
    }

    @Bean
    public Job job(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
        return jobBuilderFactory.get("job")
                .start(step(stepBuilderFactory, null))
                .build();
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(SO64447747WithJobParameter.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        JobParameters jobParameters = new JobParametersBuilder()
                .addLong("chunkSize", 2L)
                .toJobParameters();
        jobLauncher.run(job, jobParameters);
    }

}

This gives the same output as the first example.

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

How to access `with`-context from other scope in Python?

分類Dev

How to pass secrets into the test execution context from VSTS

分類Dev

Spring Batch job execution status in response body

分類Dev

Passing execution context in JavaScript from html elements

分類Dev

Execution context's in JavaScript

分類Dev

Execution context confusion

分類Dev

Removing Spring Beans from Application Context

分類Dev

'Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection

分類Dev

Spring webflux error handler: How to get the reactor context of the request in the error handler?

分類Dev

How to build spring boot application which should import spring context file from dependent jars?

分類Dev

How to assign a scope to a sublime text 3 context menu?

分類Dev

How to access root context from a composition function in Vue Composition API / Vue 3.0 + TypeScript?

分類Dev

How to access a directory outside docker context to be able access a nuget/project

分類Dev

Spring Security: How can I set a RememberMe cookie url path, that differs from the context path?

分類Dev

Cannot access a disposed object. A common cause of this error is disposing a context

分類Dev

Spring Batch:scope( "step")が失敗しました

分類Dev

Mocking a bean in a Spring context

分類Dev

How to update jsp status (from submitted to processing then success )if a spring batch job runing in background that will update a sql result status

分類Dev

Meteor access data context in onCreated

分類Dev

How to initialize test class before context initialization while Spring testing?

分類Dev

How to get the context of the current request in spring-webflux

分類Dev

Spring MVC: How to get context param when instantiate the bean?

分類Dev

using ajax context does not resolve scope issue

分類Dev

How do I solve "Reactive<_>' is ambiguous" error in tableView context

分類Dev

PHP - How to solve error "using $this when not in object context"?

分類Dev

Adding Plugins to Application Context in Spring

分類Dev

Spring security context, several users

分類Dev

How to handle this validation context?

分類Dev

How to pass a context as a parameter

Related 関連記事

  1. 1

    How to access `with`-context from other scope in Python?

  2. 2

    How to pass secrets into the test execution context from VSTS

  3. 3

    Spring Batch job execution status in response body

  4. 4

    Passing execution context in JavaScript from html elements

  5. 5

    Execution context's in JavaScript

  6. 6

    Execution context confusion

  7. 7

    Removing Spring Beans from Application Context

  8. 8

    'Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection

  9. 9

    Spring webflux error handler: How to get the reactor context of the request in the error handler?

  10. 10

    How to build spring boot application which should import spring context file from dependent jars?

  11. 11

    How to assign a scope to a sublime text 3 context menu?

  12. 12

    How to access root context from a composition function in Vue Composition API / Vue 3.0 + TypeScript?

  13. 13

    How to access a directory outside docker context to be able access a nuget/project

  14. 14

    Spring Security: How can I set a RememberMe cookie url path, that differs from the context path?

  15. 15

    Cannot access a disposed object. A common cause of this error is disposing a context

  16. 16

    Spring Batch:scope( "step")が失敗しました

  17. 17

    Mocking a bean in a Spring context

  18. 18

    How to update jsp status (from submitted to processing then success )if a spring batch job runing in background that will update a sql result status

  19. 19

    Meteor access data context in onCreated

  20. 20

    How to initialize test class before context initialization while Spring testing?

  21. 21

    How to get the context of the current request in spring-webflux

  22. 22

    Spring MVC: How to get context param when instantiate the bean?

  23. 23

    using ajax context does not resolve scope issue

  24. 24

    How do I solve "Reactive<_>' is ambiguous" error in tableView context

  25. 25

    PHP - How to solve error "using $this when not in object context"?

  26. 26

    Adding Plugins to Application Context in Spring

  27. 27

    Spring security context, several users

  28. 28

    How to handle this validation context?

  29. 29

    How to pass a context as a parameter

ホットタグ

アーカイブ