복붙노트

[SPRING] @jobscope 빈을 Spring batch에서 분할 단계로 액세스

SPRING

@jobscope 빈을 Spring batch에서 분할 단계로 액세스

분할 된 단계에서 @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에있는 클라이언트 클래스는 모든 작업을 실행할 때 특정 작업이 필요하기 때문에 필요합니다.

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

다음은 master partitioningCaptureStep에서 분할 된 단계로 호출되는 captureErpStockDBTasklet입니다.

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

구성 클라이언트에서 @StepScope로 변경하면 제대로 작동하지만 원하는 단계가 아닌 클라이언트를 생성 할 때보 다 전체 작업에 하나씩 갖고 싶습니다.

해결법

  1. ==============================

    1.파티션 된 단계에서 Job Scope 빈을 사용할 때 이것이 스프링 배치의 문제라고 생각합니다.

    파티션 된 단계에서 Job Scope 빈을 사용할 때 이것이 스프링 배치의 문제라고 생각합니다.

    참조 : https://jira.spring.io/browse/BATCH-2269 과 Spring Batch 3.0의 Job Scope 빈에 대한 멀티 스레드 액세스

  2. from https://stackoverflow.com/questions/28943123/access-jobscope-bean-in-spring-batch-with-partitioned-step by cc-by-sa and MIT license