Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从Spring批处理步骤访问执行上下文?错误:没有可用于作业范围的上下文持有者_Java_Spring_Spring Boot_Spring Batch - Fatal编程技术网

Java 如何从Spring批处理步骤访问执行上下文?错误:没有可用于作业范围的上下文持有者

Java 如何从Spring批处理步骤访问执行上下文?错误:没有可用于作业范围的上下文持有者,java,spring,spring-boot,spring-batch,Java,Spring,Spring Boot,Spring Batch,我试图在运行时设置spring批处理作业的块大小,方法是将其注入步骤中,如下所示: @Bean @JobScope @Qualifier("myStep") public Step myStep(@Value("#{jobExecutionContext['chunkSize']}") Integer chunkSize, StepBuilderFactory stepBuilderFactory, ItemReader<Object> rea

我试图在运行时设置spring批处理作业的块大小,方法是将其注入步骤中,如下所示:

@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();
}
@Bean
@工作范围
@限定词(“myStep”)
公共步骤myStep(@Value(“#{jobExecutionContext['chunkSize']}”)整数chunkSize,StepBuilderFactory StepBuilderFactory,ItemReader,ItemWriter-writer,Listener-Listener){
返回stepBuilderFactory.get(“myStep”)
.chunk(chunkSize)
.读卡器(读卡器)
.作者(作者)
.listener(侦听器)
.build();
}
但是我得到了以下错误:java.lang.IllegalStateException:没有可用于作业范围的上下文持有者

我在网上做了一些研究,但不明白为什么我会遇到这个例外。如果您能帮助我理解这个错误的含义以及如何解决它,我将不胜感激。谢谢


我在数据库表中为每个需要运行的作业定义了块大小。区块大小通过作业中此步骤之前运行的tasklet放入执行上下文

下面是一个简单的示例,其效果与预期一致:

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());
    }

}
我试图将区块大小作为作业参数传递,但在作业范围方面我看到了相同的问题

当将
chunkSize
作为作业参数传递时,相同的方法毫无例外地工作:

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);
    }

}
导入java.util.array;
导入org.springframework.batch.core.Job;
导入org.springframework.batch.core.JobParameters;
导入org.springframework.batch.core.JobParametersBuilder;
导入org.springframework.batch.core.Step;
导入org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
导入org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
导入org.springframework.batch.core.configuration.annotation.JobScope;
导入org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
导入org.springframework.batch.core.launch.JobLauncher;
导入org.springframework.batch.core.listener.ChunkListenerSupport;
导入org.springframework.batch.core.scope.context.ChunkContext;
导入org.springframework.batch.item.support.ListItemReader;
导入org.springframework.beans.factory.annotation.Value;
导入org.springframework.context.ApplicationContext;
导入org.springframework.context.annotation.AnnotationConfigApplicationContext;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
@配置
@启用批处理
带有JobParameter的公共类SO64447747{
@豆子
@工作范围
公共步骤步骤(StepBuilderFactory StepBuilderFactory,@Value(“#{jobParameters['chunkSize']}”)整数chunkSize){
返回stepBuilderFactory.get(“步骤”)
.chunk(chunkSize)
.reader(新的ListItemReader(Arrays.asList(1,2,3,4)))
.writer(items->items.forEach(System.out::println))
.listener(新的ChunkListenerSupport(){
@凌驾
chunkforecunk之前的公共void(ChunkContext上下文){
System.out.println(“开始处理新的大小块”+chunkSize);
}
})
.build();
}
@豆子
公共作业作业(JobBuilderFactory JobBuilderFactory、StepBuilderFactory StepBuilderFactory){
返回jobBuilderFactory.get(“作业”)
.start(步骤(stepBuilderFactory,null))
.build();
}
公共静态void main(字符串[]args)引发异常{
ApplicationContext context=new AnnotationConfigApplicationContext(SO64447747WithJobParameter.class);
JobLauncher JobLauncher=context.getBean(JobLauncher.class);
Job=context.getBean(Job.class);
JobParameters JobParameters=新的JobParametersBuilder()
.addLong(“块大小”,2L)
.toJobParameters();
jobLauncher.run(作业、作业参数);
}
}

这给出了与第一个示例相同的输出。

有什么理由尝试从执行上下文而不是从作业参数获取
chunkSize
?如何/何时将
chunkSize
键放入执行上下文?我在数据库表中为需要运行的每个作业定义了块大小。区块大小通过在作业中此步骤之前运行的tasklet放入执行上下文。我试图将区块大小作为作业参数传递,但我看到了与作业范围相关的相同问题。感谢您提供的示例代码,我能够理解导致错误的原因。我在工作中使用了.flow来定义步骤顺序,而我本应该使用上面提到的.start。谢谢你的帮助!
.flow
语法有一个bug(请参阅),将在即将发布的4.3版本中修复。
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);
    }

}