inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링 배치

JobExplorer / JobRegistry / JobOperator

Step에 @JobScope 걸어두면 stop할때 No context holder available for job scope 에러가 발생합니다.

2894

이기수

작성한 질문수 1

0

Step에 @JobScope 걸어두면 stop할때 No context holder available for job scope 에러가 발생합니다.
원래 그런건가요? 아니면 제가 코드를 잘못짠건가요?

spring-boot spring-batch

답변 3

1

정수원

@JobScope 를 선언하게 되면 Step 은 빈이 아닌 프록시로 생성이 됩니다.

이 말은 jobOperator.stop(jobExecution.getId()) 의 실행되는 과정 중에 어떤 시점에서 Step 의 프록시가 아닌 실제 Step 객체를 참조하게 된다면 JobContext 에서 Step 의 객체를 찾게 되는데 해당 Step 을 저장할   JobContext 객체가 생성하기 전에 호출이 발생해서 일어나는 예외입니다.

@JobScope 를 선언하면 Step 마다 새로운 객체가 생성되기 때문에 Step 을 저장하는 JobContext 도 런타임때 생성이 됩니다.

이 부분은 사실 복잡도가 있는 부분입니다.

그리고 @JobScope 는 실시간적으로 웹에서 Job 이나 Step 를 제어하는 곳에서는 객체의 생성시점을 정확하게 동기화하기가 어렵기 때문에 스프링 배치 설정에서만 사용하길 권장합니다.

디버그 하면

그래서 이런 오류가 발생하고 있습니다. 

@JobScope 를 선언하지 않으면 정상작동 합니다.

@JobScope 와 @StepScope 는 강의에서 자세히 설명하고 있으니 참고 바라며 적절한 상황에서 잘 사용해야 하는 기술입니다. 

0

이기수

BatchConfig.java

@Configuration
@RequiredArgsConstructor
public class BatchConfig {
	private final JobRegistry jobRegistry;
	
	@Bean
	public BeanPostProcessor JobRegistryBeanPostProcessor() {
		JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor();
		jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry);
		return jobRegistryBeanPostProcessor;
	}
}

 

MyJobConfig.java


@Configuration
@RequiredArgsConstructor
public class MyJobConfig {
	private final JobBuilderFactory jobBuilderFactory;
	private final StepBuilderFactory stepBuilderFactory;
	
	@Bean
	public Job myJob() {
		return jobBuilderFactory.get("myJob")
				.start(myStep1())
				.next(myStep2())
				.build();
	}
	
	@Bean
	@JobScope
	public Step myStep1() {
		return stepBuilderFactory.get("myStep1")
				.tasklet((contribution, context) -> {
					System.out.println("myStep1 start");
					Thread.sleep(10000);
					System.out.println("myStep1 end");
					return RepeatStatus.FINISHED;
				})
				.build();
	}
	
	@Bean
	@JobScope
	public Step myStep2() {
		return stepBuilderFactory.get("myStep2")
				.tasklet((contribution, context) -> {
					System.out.println("myStep2 start");
					Thread.sleep(10000);
					System.out.println("myStep2 end");
					return RepeatStatus.FINISHED;
				})
				.build();
	}
}

 

BatchController.java

@RestController
@RequiredArgsConstructor
@RequestMapping("/batch")
public class BatchController {
	private final JobOperator jobOperator;
	private final JobRegistry jobRegistry;
	private final JobExplorer jobExplorer;
	
	@GetMapping("/start")
	public String jobStart(String data) throws NoSuchJobException, JobInstanceAlreadyExistsException, JobParametersInvalidException {
		for(String jobName : jobRegistry.getJobNames()) {
			 jobOperator.start(jobName, "data="+data);
		}
		return "SUCCESS";
	}
	
	@GetMapping("/restart")
	public String jobRestart(String data) throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException, NoSuchJobException, JobRestartException, JobParametersInvalidException {
		for(String jobName : jobRegistry.getJobNames()) {
			Long executionId = jobExplorer.getLastJobExecution(jobExplorer.getLastJobInstance(jobName)).getId();
			jobOperator.restart(executionId);
		}
		return "SUCCESS";
	}
	
	@GetMapping("/stop")
	public String jobStop() throws NoSuchJobExecutionException, JobExecutionNotRunningException  {
		for(String jobName : jobRegistry.getJobNames()) {
			for(JobExecution jobExecution : jobExplorer.findRunningJobExecutions(jobName)) {				
				jobOperator.stop(jobExecution.getId());
			}
		}
		return "SUCCESS";
	}
}

 

위 코드에서 http://localhost:8080/batch/start?data=data로 job실행하고, 끝나기전에 http://localhost:8080/batch/stop 호출하면 "java.lang.IllegalStateException: No context holder available for job scope" 에러 발생합니다.

0

정수원

전체 코드 좀 볼 수 있을까요?

스프링 배치 버전 질문

0

141

1

소스코드가 어디에 있나요?

0

122

2

트랜잭션 예외

0

101

1

질문이 있습니다.

0

140

2

ChunkListener 에서 beforeChunk 의 실행 시점 관련 질문

0

146

2

여러 JOB 설정하는법

0

158

2

강의 자료 다른 방법 있을까요?

0

163

1

JobExecution과 JobExecutionContext와의 관계

0

198

2

특정 job만 실행

1

271

1

Batch 성능 질문

0

158

1

ItemReaderAdapter 종료

0

87

1

[ 강좌 Git 브랜치 문의 ] 섹션 9 > JdbcCursorItemReader, JpaCursorItemReader

0

191

2

Spring Batch 배포 질문

0

254

2

spring batch 버전

0

239

2

retry count 관련 질문

0

185

2

StepExecutionListener 의 afterStep 에서 return ExitStatus.FAILED 에 의한 동작에 의문이 갑니다.

0

346

2

jdbc, jpa 커서방식 조회 방식 차이 질문 (강사님께 답변 받고 싶습니다)

0

242

2

Multithread step과 AsyncItemProcessor

0

208

2

job 재실행

0

259

2

bean 생명주기 문제 도와주세요(@Scope("step"), @Autowired)

0

192

1

Multi-threaded-step과 Partitioning 차이 확인

0

186

2

jdbcCursorReader, jdbcPagingReader 질문

0

149

1

step muti-thread 질문

0

114

1

itemSteam open update close 질문

0

120

1