[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.파티션 된 단계에서 Job Scope 빈을 사용할 때 이것이 스프링 배치의 문제라고 생각합니다.
파티션 된 단계에서 Job Scope 빈을 사용할 때 이것이 스프링 배치의 문제라고 생각합니다.
참조 : https://jira.spring.io/browse/BATCH-2269 과 Spring Batch 3.0의 Job Scope 빈에 대한 멀티 스레드 액세스
from https://stackoverflow.com/questions/28943123/access-jobscope-bean-in-spring-batch-with-partitioned-step by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] MockRestServiceServer로 RestTemplate을 조롱하는 법? (0) | 2019.07.13 |
---|---|
[SPRING] Junit에서 @Autowired 주석과 함께 @InjectMocks를 사용하는 방법 (0) | 2019.07.13 |
[SPRING] Spring 데이터 나머지 @EmbeddedId는 Post 요청에서 생성 할 수 없습니다. (0) | 2019.07.13 |
[SPRING] Spring 설정에서 빈 arraylists를 초기화 하시겠습니까? (0) | 2019.07.13 |
[SPRING] @Autowired (required = false) 생성자에서 NoSuchBeanDefinitionException을 제공함 (0) | 2019.07.13 |