Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.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
Spring boot @在异步处理器中未调用beforstep_Spring Boot_Asynchronous_Spring Batch_Batch Processing_Spring Batch Tasklet - Fatal编程技术网

Spring boot @在异步处理器中未调用beforstep

Spring boot @在异步处理器中未调用beforstep,spring-boot,asynchronous,spring-batch,batch-processing,spring-batch-tasklet,Spring Boot,Asynchronous,Spring Batch,Batch Processing,Spring Batch Tasklet,我一直在使用synchronous ItemProcessor和Writer,但现在我将其改为Asynchronous,代码如下: @Bean public Job importFraudCodeJob(Step computeFormFileToDB) { return jobBuilderFactory.get("Import-Entities-Risk-Codes") .incrementer(new RunIdIncrementer()

我一直在使用synchronous ItemProcessor和Writer,但现在我将其改为Asynchronous,代码如下:

@Bean
public Job importFraudCodeJob(Step computeFormFileToDB) {
    return jobBuilderFactory.get("Import-Entities-Risk-Codes")
            .incrementer(new RunIdIncrementer())
            .listener(notificationExecutionListener)
            .start(computeFormFileToDB)
            .build();
}
@Bean
public Step computeFormFileToDB(ItemReader<EntityRiskCodesDto> entityRiskCodeFileReader) {
    return stepBuilderFactory.get("ImportFraudCodesStep")
            .<EntityFraudCodesDto, Future<EntityFraudCodes>>chunk(chunkSize)
            .reader(entityRiskCodeFileReader)
            .processor(asyncProcessor())
            .writer(asyncWriter())
            .faultTolerant()
            .skipPolicy(customSkipPolicy)
            .listener(customStepListener)
            .listener(chunkCounterListener())
            .taskExecutor(taskExecutor())
            .throttleLimit(6)
            .build();
}
这里是我的异步处理器声明:

  @Bean
public AsyncItemProcessor<EntityRiskCodesDto, EntityRiskCodes> asyncProcessor() {
    var asyncItemProcessor = new AsyncItemProcessor<EntityRiskCodesDto, EntityRiskCodes>();
    asyncItemProcessor.setDelegate(riskCodeItemProcessor());
    asyncItemProcessor.setTaskExecutor(taskExecutor());
    return asyncItemProcessor;
}
@Bean
公共AsyncItemProcessor asyncProcessor(){
var asyncItemProcessor=新的asyncItemProcessor();
setDelegate(riskCodeItemProcessor());
setTaskExecutor(taskExecutor());
返回异步项处理器;
}
问题是上面的方法没有被调用。
如何从StepExecution获取值并将其传递到异步项目处理器或AsyncItemWiter?

原因是,由于您的项目处理器是异步项目处理器的委托,因此它不会自动注册为侦听器,这应该手动完成。以下是文件部分的摘录:

If the listener is nested inside another component, it needs to be explicitly
registered (as described previously under "Registering ItemStream with a Step").
因此,在您的用例中,您需要在步骤中将委托
riskCodeItemProcessor()
注册为侦听器,并且应该调用用
@beforstep
注释的方法。下面是一个简单的例子:

import java.util.Arrays;
import java.util.concurrent.Future;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.integration.async.AsyncItemProcessor;
import org.springframework.batch.integration.async.AsyncItemWriter;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

@Configuration
@EnableBatchProcessing
public class MyJobConfig {

    @Bean
    public ItemReader<Integer> itemReader() {
        return new ListItemReader<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
    }

    @Bean
    public ItemProcessor<Integer, Integer> itemProcessor() {
        return new MyItemProcessor();
    }

    @Bean
    public AsyncItemProcessor<Integer, Integer> asyncItemProcessor() {
        AsyncItemProcessor<Integer, Integer> asyncItemProcessor = new AsyncItemProcessor<>();
        asyncItemProcessor.setDelegate(itemProcessor());
        asyncItemProcessor.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return asyncItemProcessor;
    }

    @Bean
    public ItemWriter<Integer> itemWriter() {
        return items -> {
            for (Integer item : items) {
                System.out.println(Thread.currentThread().getName() + ": item = " + item);
            }
        };
    }
    
    @Bean
    public AsyncItemWriter<Integer> asyncItemWriter() {
        AsyncItemWriter<Integer> asyncItemWriter = new AsyncItemWriter<>();
        asyncItemWriter.setDelegate(itemWriter());
        return asyncItemWriter;
    }

    @Bean
    public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
        return jobs.get("myJob")
                .start(steps.get("myStep")
                        .<Integer, Future<Integer>>chunk(5)
                        .reader(itemReader())
                        .processor(asyncItemProcessor())
                        .writer(asyncItemWriter())
                        .listener(itemProcessor())
                        .build())
                .build();
    }

    static class MyItemProcessor implements ItemProcessor<Integer, Integer> {

        private StepExecution stepExecution;
        
        @Override
        public Integer process(Integer item) throws Exception {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + ": processing item " + item 
                    + " as part of step " + stepExecution.getStepName());
            return item + 1;
        }

        @BeforeStep
        public void saveStepExecution(StepExecution stepExecution) {
            this.stepExecution = stepExecution;
        }
    }

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

}

也就是说,不建议在多线程设置中依赖执行上下文,因为该上下文在线程之间共享。

您的异步项目处理器是否声明为bean?字段上的注释本身不会改变对象。您需要将处理器声明为bean,以便Spring批处理对注释进行内省并相应地代理bean。否则,您需要实现
StepExecutionListener
,并将bean注册为侦听器。注意,不建议在多线程设置中依赖执行上下文。谢谢,Mahmoud,我的异步处理器声明为Bean。您现在可以在我的代码中看到。我真正想要实现的是如何在使用AsyncItemProcessor时获取存储在stepExecutionContext中的值?有什么方法或例子吗?谢谢你的回复。我用一个例子补充了一个答案。希望能有帮助。像往常一样,谢谢,我试着读过医生,但由于某种原因,它失败了。因此,在本例中,上下文在线程之间共享,但在我的示例中,我保证只读取@beforstep中添加的值。谢谢你的例子。不客气,很高兴它有帮助!当然,如果共享状态是线程安全的,那么可以将其放在执行上下文中。
import java.util.Arrays;
import java.util.concurrent.Future;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.BeforeStep;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.integration.async.AsyncItemProcessor;
import org.springframework.batch.integration.async.AsyncItemWriter;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

@Configuration
@EnableBatchProcessing
public class MyJobConfig {

    @Bean
    public ItemReader<Integer> itemReader() {
        return new ListItemReader<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
    }

    @Bean
    public ItemProcessor<Integer, Integer> itemProcessor() {
        return new MyItemProcessor();
    }

    @Bean
    public AsyncItemProcessor<Integer, Integer> asyncItemProcessor() {
        AsyncItemProcessor<Integer, Integer> asyncItemProcessor = new AsyncItemProcessor<>();
        asyncItemProcessor.setDelegate(itemProcessor());
        asyncItemProcessor.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return asyncItemProcessor;
    }

    @Bean
    public ItemWriter<Integer> itemWriter() {
        return items -> {
            for (Integer item : items) {
                System.out.println(Thread.currentThread().getName() + ": item = " + item);
            }
        };
    }
    
    @Bean
    public AsyncItemWriter<Integer> asyncItemWriter() {
        AsyncItemWriter<Integer> asyncItemWriter = new AsyncItemWriter<>();
        asyncItemWriter.setDelegate(itemWriter());
        return asyncItemWriter;
    }

    @Bean
    public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
        return jobs.get("myJob")
                .start(steps.get("myStep")
                        .<Integer, Future<Integer>>chunk(5)
                        .reader(itemReader())
                        .processor(asyncItemProcessor())
                        .writer(asyncItemWriter())
                        .listener(itemProcessor())
                        .build())
                .build();
    }

    static class MyItemProcessor implements ItemProcessor<Integer, Integer> {

        private StepExecution stepExecution;
        
        @Override
        public Integer process(Integer item) throws Exception {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + ": processing item " + item 
                    + " as part of step " + stepExecution.getStepName());
            return item + 1;
        }

        @BeforeStep
        public void saveStepExecution(StepExecution stepExecution) {
            this.stepExecution = stepExecution;
        }
    }

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

}
SimpleAsyncTaskExecutor-1: processing item 0 as part of step myStep
SimpleAsyncTaskExecutor-2: processing item 1 as part of step myStep
SimpleAsyncTaskExecutor-3: processing item 2 as part of step myStep
SimpleAsyncTaskExecutor-4: processing item 3 as part of step myStep
SimpleAsyncTaskExecutor-5: processing item 4 as part of step myStep
main: item = 1
main: item = 2
main: item = 3
main: item = 4
main: item = 5
SimpleAsyncTaskExecutor-6: processing item 5 as part of step myStep
SimpleAsyncTaskExecutor-7: processing item 6 as part of step myStep
SimpleAsyncTaskExecutor-8: processing item 7 as part of step myStep
SimpleAsyncTaskExecutor-9: processing item 8 as part of step myStep
SimpleAsyncTaskExecutor-10: processing item 9 as part of step myStep
main: item = 6
main: item = 7
main: item = 8
main: item = 9
main: item = 10