error

[에러해결] Unexpected error occurred in scheduled task

!쪼렙조햄 2022. 9. 13. 14:18
반응형
Unexpected error occurred in scheduled task
org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only

기존에 스프링부트 + JPA 를 사용해서 
백엔드를 구축 중이었당

이번에 주기적인 알람 기능을 구현하면서
@Scheduled 어노테이션을 사용하게 되었고

자연스럽게 @Transactional 어노테이션이 붙어있던 트랜잭션에
@Scheduled 어노테이션을 붙여서 사용하게 되었다

그러나 Unexpected error occurred in scheduled task 에러
발생..

구글링을 하다가 발견한
갓영한님의 목소리

아니..!!!!!

몰랐어요..!!!!!

왜 @Scheduled 와 @Transactional 어노테이션을 분리해야 하는가

자 일단
@Transactional 은 스프링에서 제공해주는 AOP functionality 라고 한다

그래서 요 어노테이션이 붙은 메소드는
다른 bean 에서 불리웠을때 정상 동작을 한다고 한다

그리고.. 뭐.. 요렇다고 하는데..

@Transactional annotation is processed. It create proxy which store reference to original bean. Original bean is replaced to proxy in application context.

미래의 내가 이해하겠지..(?)

그래서 해결법

두 메소드를 동시에 두지 않고
한 메소드에 한 어노테이션만 두자

아래와 같은 늑낌으루~

@Service
public class UserServiceImpl implements UserService {

    @Override
    @Transactional
    public void doSomething() {

    }
}

@Service
public class UserServiceScheduler {

    @Inject
    private UserService service;

    @Scheduled(fixedRateString = "${somestring}",initialDelayString = "${anotherstring}")
    public void doSomething() {
         service.doSomething();
    }
}

 

나의 케이스

내 케이스에서는 사실
@Transactional 과 @Scheduled 를 함께 쓸 이유가 딱히 없었다

(같이 썼던 메소드가 10개라면 그중 8개 정도는 Transactional이 불필요 했던듯)

거의 그냥 db의 데이터들을 읽어오는 메소드 들이었기 때무네...

이건 그냥 내가
Transactional 어노테이션이 좋다던데~
이렇게 짧게 알아서 벌어진 일 ㅎ

그러나 아직 문제는 완벽히 해결되지 못했다

JPA repository 의 save 메소드에는
내부적으로 @Transactional 이 붙어있다고 한다

그래서 그 외부 메소드에
@Transactional 을 쓰려면
트랜잭션을 상속받는 방식중에 뭘 쓸지를 골라야 한다는것!!

결국 나는 이 문제 해결을 위해서

문제가 되는 부분들의
Transactional 어노테이션을 다 제거해버렸다

흐음 이게 맞나..?

처음에 Transactional 어노테이션을 붙였던 이유는
알람을 보내는 로직에서

1. 알람을 보냈다고 db에 알람 기록한 시점도 저장하고 (repository.save())
2. firebase 알람 시스템을 이용해서 알람을 보내는

위 2개 로직이
둘중에 실패했을때 롤백되기를 원했다

그래서 2개 로직을 하나의 함수로 묶어서
그 위에 Transactional을 달았는데..

why..

Reference

1. 나같이 @Scheduled @Transactional 같이 쓰면 웨 않되요? 하는 스택오버플로우
https://stackoverflow.com/questions/45355601/why-scheduled-annotation-doesnt-work-with-transaction-annotation-spring-boot

2. 갓영한님의 답변이 담긴 인프런 질의응답
https://www.inflearn.com/questions/297130

3. JPA의 save 에는 이미 @Transactional이 달려있는데, 외부메소드에도 @Transactional 있을때 해결책 3개 제시해주는 포스팅
https://ws-pace.tistory.com/138

 

반응형