티스토리 뷰

티스토리

어떤 유저가 회원가입을 하거나 수정을 했을 때 메일을 발송해야하는 기능을 구현해야했다.

 

@TransactionalEventListener를 이용하여 이 것을 해결했는데

기본 코드는 작년 프로젝트 코드를 참고 하였고, 메일을 발송하는 기능 자체는 회사 내부 다른팀의 api(외부 api)를 이용하였다.

 

흐름 자체는 외부 api를 통해 메일 내용을 등록해놓는 것이었고,

내부 코드에서는 CRUD가 일어났을 때 EventListener가 실행될 수 있도록 되어있었는데, 이 부분에서 작은 문제가 생겼다.

 

@Override
public UserDto createUser(LoggedInUser loggedInUser, RequestUserDto request) {
		UserEntity originUser = userRepository.findById(loggedInUser.getId())
                .orElseThrow(() -> new Exception();
        UserDto user = MapperHolder.modelMapper().map(request, UserDto.class);
        originUser = userEntity.createUser(user);
        originUser = userRepository.save(originUser);
        UserDto userDto = MapperHolder.modelMapper().map(userEntity, UserDto.class);
        applicationEventListener.isEvent(ApiEvent.of(userDto));
        return userDto;
}

해당 Service를 보면 Repository에 svae를 하는 것을 볼 수 있고, return 전 EventListener를 호출하고 있지만 실제 메일 발송이 안되었다.

interface인 EventListener의 구현체로 들어가보면 아래의 코드와 같이 구현되어 있는데

 

  @TransactionalEventListener
    public void apiCommit(UserDto event) { 
    ....
    }

Method에 @TransactionalEventListener 어노테이션이 추가되어있다.

 

코드를 구현한 부분엔 큰 문제가 없어보이는데 왜 동작하지 않을까?

이 것에 대한 해답은 '영속성 컨텍스트'에 있는 것으로 추측하였다.

 

@TransactionalEventListener는 말 그대로 트랜젝션이 일어났을 때 이벤트를 읽어 실행하는 형태로 되어있다.

createUser Method를 보면 @Transactional 어노테이션은 붙어있지 않고 repository를 직접 불러 save를 하기 때문에

영속성 컨텍스트 관점에선 originUser = userRepository.save(originUser); 라인에서 종료될 것이다.

 

그렇기 때문에 applicationEventListener으로 이벤트를 읽어봤자 CRUD가 일어난것을 감지 하지 못하는 것 같아

createUser Method에 @Transactional 어노테이션을 추가하니 정상적으로 메일이 발송되는 것을 확인 할 수 있었다.

 

  • 회고

이번에 처음으로 EventListener를 사용해봤는데 자주 사용할 기능이니 나중을 위해 좀 더 공부해봐야겠습니다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함