강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

blueraint님의 프로필 이미지
blueraint

작성한 질문수

스프링 배치

AsyncItemProcessor / AsyncItemWriter

AsyncItemWriter 의 Transaction 범위 관련

작성

·

562

0

안녕하세요 질문이 있어서 글을 남깁니다.

현재 저는 다중 데이터베이스 기반의 배치 Call 서버를 제작중에 있습니다.

한개의 데이터베이스는 Batch Metadata 저장 서버로, 다른 서버를 Datasource로 가져와서 ItemReader 나 Writer 로 사용하고 있습니다(2개의 datasource 지정)

 

다중서버 구성시 JpaItemWriter를 이용하게 되면, repository의 트랜잭션 보장 문제로 인하여 'no transaction in progress'문제가 생겼고, 해당 문제 확인 결과 stepBuilderFactory.transcationManager(PlatformTransactionManager)으로 다중 datasource에 writer를 처리할 수 있음을 알게 되었습니다.

 

async방식의 처리에서 AsyncItemWriter도 같은 방식으로 transactionManager를 처리하였는데, 두가지의 문제가 발생하였습니다.

 

1) AsyncItemWriter에서 delegate시에 transactionManager 이 적용이 안되는지, 'no transaction is in progress' 가 발생합니다. 제가 주입하고자 하는 transactionManager가 적용이 안되고 delegate시 알아서 시스템이 자동 주입을 하는거 같은데, 해당 현상에 대한 해결방법을 알고싶습니다.

* 해당 현상에 대한 에러는 하단에 남깁니다. ItemWriter 구현체는 JpaItemWriter입니다

 

2) 강사님의 강의에서도 나온 문제인데, StepBuilderFactory 반환에서 Warning이 발생하고 있습니다.(AsyncItemWriter 강의 21:50경) 타입을 체크하지 않고 발생하는 오류인데, 타입을 제대로 주면 Future때문인지 명확하게 warning이 해결되지 않고 있습니다. 이건 어노테이션으로 워닝 무시를 해야할 수 밖에 없는 것인지 알고 싶습니다.

* 아마도 stepbuildFactory의 <input, output> 값이 <InputEntity, Future<OutputEntity>> 가 되어야 하는 것이 맞아보이는데 맞는지요?

 

에러)

22:51 INFO  o.s.batch.core.job.SimpleStepHandler - Executing step: [asyncInitializationStep1]

22:51 ERROR o.s.batch.core.step.AbstractStep - Encountered an error executing step asyncInitializationStep1 in job initializationJob

javax.persistence.TransactionRequiredException: no transaction is in progress

at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:445)

at org.hibernate.internal.SessionImpl.checkTransactionNeededForUpdateOperation(SessionImpl.java:3478)

at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1394)

at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1389)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.base/java.lang.reflect.Method.invoke(Method.java:566)

at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:362)

at com.sun.proxy.$Proxy137.flush(Unknown Source)

at org.springframework.batch.item.database.JpaItemWriter.write(JpaItemWriter.java:94)

at org.springframework.batch.integration.async.AsyncItemWriter.write(AsyncItemWriter.java:85)

at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:193)

at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:159)

at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:294)

at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:217)

at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77)

at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407)

at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331)

at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)

at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273)

at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82)

at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375)

at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)

at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145)

at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258)

at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.base/java.lang.reflect.Method.invoke(Method.java:566)

at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)

at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)

at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137)

at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)

at com.sun.proxy.$Proxy148.execute(Unknown Source)

at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:152)

at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:413)

at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136)

at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:320)

at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:149)

at java.base/java.lang.Thread.run(Thread.java:829)

22:51 INFO  o.s.batch.core.step.AbstractStep - Step: [asyncInitializationStep1] executed in 9s902ms

22:51 INFO  o.s.b.c.l.support.SimpleJobLauncher - Job: [SimpleJob: [name=initializationJob]] completed with the following parameters: [{firmCode=0001, fileType=fixed, executeDate=1646661075421}] and the following status: [FAILED] in 9s960ms

 

퀴즈

스프링 배치에서 멀티스레딩을 적용하는 주된 목적은 무엇일까요?

배치 작업의 디버깅을 쉽게 만들기 위함

배치 작업의 처리량을 늘리고 성능을 향상시키기 위함

배치 작업 설정 파일의 복잡성을 줄이기 위함

데이터베이스 연결 수를 줄이기 위함

답변 1

0

정수원님의 프로필 이미지
정수원
지식공유자

정확한 분석을 위해 소스 공유 부탁드립니다

blueraint님의 프로필 이미지
blueraint

작성한 질문수

질문하기