Java-Bom / ReadingRecord

📚 책 읽고 정리하기 📚
https://javabom.tistory.com/category/Reading%20Record
473 stars 27 forks source link

[13장] 스텝 테스트하기 #242

Closed BangKiHyun closed 3 years ago

BangKiHyun commented 3 years ago

p.674 @Transactional(propagation = Propagation.NOT_SUPPORTED): 스프링 배치가 트랜잭션을 관리하면서 다른 트랜잭션으로 래핑하면 실제로 오류가 발생한다.

질문 : 실제로 @Transactional(propagation = Propagation.NOT_SUPPORTED)애노테이션을 제거하고 테스트를 실행해 보았는데 @Transaction애노테이션을 제거하라는 오류메시지가 뜹니다. 이러한 문제가 발생하는 이유가 정확히 이해가 되지 않아 질문드립니다!

chldbtjd2272 commented 3 years ago

스프링 배치 실행시 자신이 트랜잭션을 제어해야하는데 다른 트랜잭션으로 래핑하면 정상수행이 불가능합니다 *job 수행시 jobRepository 트랜잭션을 관리합니다

class AbstractJobRepositoryFactoryBean {

....
private void initializeProxy() throws Exception {
        if (proxyFactory == null) {
            proxyFactory = new ProxyFactory();
            TransactionInterceptor advice = new TransactionInterceptor(transactionManager,
                    PropertiesConverter.stringToProperties("create*=PROPAGATION_REQUIRES_NEW,"
                            + isolationLevelForCreate + "\ngetLastJobExecution*=PROPAGATION_REQUIRES_NEW,"
                            + isolationLevelForCreate + "\n*=PROPAGATION_REQUIRED"));
            if (validateTransactionState) {
                DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(new MethodInterceptor() {
                    @Override
                    public Object invoke(MethodInvocation invocation) throws Throwable {
                        if (TransactionSynchronizationManager.isActualTransactionActive()) {
                            throw new IllegalStateException(
                                    "Existing transaction detected in JobRepository. "
                                            + "Please fix this and try again (e.g. remove @Transactional annotations from client).");
                        }
                        return invocation.proceed();
                    }
                });
                NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
                pointcut.addMethodName("create*");
                advisor.setPointcut(pointcut);
                proxyFactory.addAdvisor(advisor);
            }
        .....
        }
    }

}

위 JobRepository 팩토리 빈 클래스를 보면 jobRepository의 create* 메서드에 advisor를 걸어 해당 메서드 호출시 transaction이 걸려있는지 여부를 판단하고 있습니다. transaction을 검사를 안하고 싶다면 validateTransactionState를 false로 바꿔서 설정하면 트스트 코드에 트랜잭션을 걸어도 통과합니다