使用分区步骤在Spring Batch中访问@JobScope bean
作者:互联网
有没有一种方法可以在分区步骤中访问定义为@JobScope的bean?
我们将http客户端bean定义为@JobScope,因为它对于每个作业都是唯一的,但是是动态创建的,因此在从属步骤中需要它来发出发布请求.当我们自动接线时,我们得到的
Error creating bean with name 'scopedTarget.captureErpStockTasklet':
Scope 'step' is not active for the current thread; consider defining a
scoped proxy for this bean if you intend to refer to it from a singleton;
nested exception is java.lang.IllegalStateException: No context holder
available for step scope
这是作业配置类(我删除了所有不需要的东西,只保留了分区步骤的配置和@JobScope中的Client类,因为在每次运行的作业中,它都必须是特定于作业的:
@Configuration
@EnableBatchProcessing
@ComponentScan(basePackages = {"com.example.importjob"})
public class FrozenFileImportJobConfig {
@Value("${thread.pool:10}")
private int threadPoolSize;
@Value("${partitioner.max.thread.pool:10}")
private int maxThreadPoolSize;
@Value("${grid.size:10}")
private int gridSize;
@Value("${client.url:some_url}")
private int url;
@Value("${client.id:client_id}")
private int clientId;
@Value("${client.secret:secret}")
private int clientSecret;
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Autowired
private ErpStockIdPartitioner erpStockIdPartitioner;
@Autowired
private CaptureErpStockTasklet captureErpStockTasklet;
@Bean(destroyMethod = "destroy")
@JobScope
public Client client() {
return new Client(url, clientId, clientSecret);
}
public ExecutionContextPromotionListener contextPromotionListener() {
final ExecutionContextPromotionListener executionContextPromotionListener = new ExecutionContextPromotionListener();
executionContextPromotionListener.setKeys(new String[] {"erp_stock_ids"});
return executionContextPromotionListener;
}
public Step captureErpStockDBTaskletStep() {
return stepBuilderFactory.get("captureErpStockDBTaskletStep").tasklet(captureErpStockTasklet).build();
}
@Bean
public ThreadPoolTaskExecutor erpStockIdTaskExecutor() {
final ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(threadPoolSize);
threadPoolTaskExecutor.setMaxPoolSize(maxThreadPoolSize);
threadPoolTaskExecutor.setAllowCoreThreadTimeOut(true);
return threadPoolTaskExecutor;
}
public Step partitioningCaptureStep() {
return stepBuilderFactory.get("partitioningCaptureStep").partitioner(captureErpStockDBTaskletStep())
.partitioner("erpStockIdPartitioner", erpStockIdPartitioner).taskExecutor(erpStockIdTaskExecutor())
.gridSize(gridSize).allowStartIfComplete(true).build();
}
@Bean
public Job riverIslandFrozenFileImportJob() {
return jobBuilderFactory.get("riverIslandFrozenFileImportJob").start(partitioningCaptureStep()).build();
}
}
这是captureErpStockDBTasklet,它是从主partitioningCaptureStep的分区步骤调用的:
@Component
@StepScope
public class CaptureErpStockTasklet implements Tasklet {
private static final Logger LOG = LoggerFactory.getLogger(CaptureErpStockTasklet.class);
@Value("#{jobParameters[" + FtpJobParameters.ORGANIZATION_ID + "]}")
private Long organizationId;
@Autowired
private ErpStockRepository erpStockRepository;
@Autowired
private Client client;
@Override
public RepeatStatus execute(final StepContribution contribution, final ChunkContext chunkContext) throws Exception {
//importing of erp stock from DB, nothing special in that code so removed
client.captureErpStock(stock);
LOG.info("[{}] Finished importing ERP {}", organizationId, erpStock);
return RepeatStatus.FINISHED;
}
}
当我在配置Clinet中将其更改为@StepScope时,它可以正常工作,但是我无法为不是我想要的每一步创建客户端,所以我希望为整个工作准备一个.
解决方法:
我认为这在春季批处理中在分区步骤中使用Job Scope Bean时是一个问题.
查看:https://jira.spring.io/browse/BATCH-2269
和
Multi-threaded acces to Job Scope beans in Spring Batch 3.0
标签:spring-batch,spring 来源: https://codeday.me/bug/20191120/2045455.html