티스토리 뷰
반응형
비즈니스 로직과 상관없지만 해야하는 일들이 있을 때, Spring 프레임워크에서 제공하는 Event를 사용하여 비즈니스 코드와 비즈니스와 관련 없는 코드의 의존을 분리한다.
예를 들어, 비즈니스 특정 행위를 로그 테이블에 적재해야 할 때, 나의 판단에는 비즈니스의 흐름에 로그 테이블에 적재하는 코드를 넣는 것은 비즈니스 흐름을 읽는 데 방해가 된다. 그래서 이벤트를 발생시키고 해당 이벤트의 Listener 객체가 해당 작업을 수행하도록 한다.
문제
최근에 컨트롤러에서 특정 익셉션이 발생하면, 이벤트를 발행하여 문제를 해결하도록 코드를 작성했다.
@GetMapping(path = ["/{id}"])
fun getSomething(
@RequestAttribute("appId") appId: Long,
@PathVariable id: Long
): ApiResponse<Something?> {
return try {
ApiResponse.okay(somethingQueryService.getSomething(appId, id))
} catch (e: SomethingException) {
log.warn(e) { "problem!" }
Events.raise(SomethingProblemEvent(id, appId))
ApiResponse.error("something error")
}
}
import mu.KotlinLogging
import org.springframework.stereotype.Component
import org.springframework.transaction.event.TransactionalEventListener
@Component
class SomethingProblemEventListener(
private val somethingProblemService: SomethingProblemService
) {
private val log = KotlinLogging.logger { }
@TransactionalEventListener
fun onSomethingProblem(event: SomethingProblemEvent) {
log.info { "event: $event" }
somethingProblemService.handle(event.id, event.appId)
}
}
그런데 이 코드는 동작하지 않았다.
원인
If the event is not published within an active transaction, the event is discarded unless the fallbackExecution() flag is explicitly set.
@TransactionalEventListener의 경우 트랜잭션 외부에서는 이벤트가 버려진다. 나는 controller에서 해당 이벤트를 발행했기 때문에 이런 문제가 발생했다.
해결
해결책은 @EventListener 를 사용하는 것! 해당 이벤트를 핸들링하는 코드가 익셉션이 발생한 비즈니스 코드와 트랜잭션으로 묶일 필요도 없고 실패하면 다시 실행하면 되는 상황이라 쉽게 결정할 수 있었다.
import mu.KotlinLogging
import org.springframework.context.event.EventListener
import org.springframework.stereotype.Component
@Component
class SomethingProblemEventListener(
private val somethingProblemService: SomethingProblemService
) {
private val log = KotlinLogging.logger { }
@EventListener
fun onSomethingProblem(event: SomethingProblemEvent) {
log.info { "event: $event" }
somethingProblemService.handle(event.id, event.appId)
}
}
반응형
'JAVA' 카테고리의 다른 글
JPA에서 SQL Error: 1064, SQLState: 42000 만났을 때 (0) | 2020.05.09 |
---|---|
JPA로 생성된 쿼리에 주석 붙이기 (0) | 2019.12.13 |
실행가능한 Groovy jar 만들기 (0) | 2018.05.31 |
Spring Boot jar에서 war로 변경 (0) | 2017.11.15 |
자바 백앤드에서 canvas의 data URL 저장하기 (3) | 2017.05.29 |
댓글
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- AWSKRUG
- container
- javascript
- 웹을 지탱하는 기술
- rest
- 개발자
- Clean code
- Bali
- 도커
- spring
- 컨테이너
- AWS
- sanur
- springboot
- 발리
- 독후감
- S68
- ecma6
- 사누르
- 객체지향
- 회고
- html
- 웹
- 한달살기
- spring boot
- ES6
- ChatGPT
- Docker
- 실수노트
- hands-on
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
글 보관함