其他分享
首页 > 其他分享> > 使用分区步骤在Spring Batch中访问@JobScope bean

使用分区步骤在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