참여중인 스터디 변경 사항에 대한 알림
- 스터디 소개가 수정 했을때
- 스터디 종료시
- 스터디 팀원 모집 시작 / 중지
스터디 소개가 수정했을때 알림을 발생시키기 위해 스터디 소개 수정, 스터디 종료, 스터디 팀원 모집, 모집 중단 시에 이벤트를 추가합니다.
package me.weekbelt.studyolle.modules.study;
@RequiredArgsConstructor
@Transactional
@Service
public class StudyService {
// .......
public void updateStudyDescription(Study study, StudyDescriptionForm studyDescriptionForm) {
modelMapper.map(studyDescriptionForm, study);
eventPublisher.publishEvent(new StudyUpdateEvent(study, "스터디 소개를 수정했습니다."));
}
// .......
public void close(Study study) {
study.close();
eventPublisher.publishEvent(new StudyUpdateEvent(study, "스터디를 종료했습니다."));
}
public void startRecruit(Study study) {
study.startRecruit();
eventPublisher.publishEvent(new StudyUpdateEvent(study, "팀원 모집을 시작합니다."));
}
public void stopRecruit(Study study) {
study.stopRecruit();
eventPublisher.publishEvent(new StudyUpdateEvent(study, "팀원 모집을 중단했습니다."));
}
// ............
}
members와 managers를 동시에 불러오는 Study 조회 메소드를 추가와 동시에 StudyRepository 리팩토링
package me.weekbelt.studyolle.modules.study;
@Transactional(readOnly = true)
public interface StudyRepository extends JpaRepository<Study, Long> {
boolean existsByPath(String path);
@EntityGraph(attributePaths = {"tags", "zones", "managers", "members"}, type = EntityGraph.EntityGraphType.LOAD)
Study findByPath(String path);
@EntityGraph(attributePaths = {"tags", "managers"})
Study findStudyWithTagsByPath(String path);
@EntityGraph(attributePaths = {"zones", "managers"})
Study findStudyWithZonesByPath(String path);
@EntityGraph(attributePaths = "managers")
Study findStudyWithManagersByPath(String path);
@EntityGraph(attributePaths = "members")
Study findStudyWithMembersByPath(String path);
Optional<Study> findStudyOnlyByPath(String path);
@EntityGraph(attributePaths = {"zones", "tags"})
Study findStudyWithTagsAndZonesById(Long id);
@EntityGraph(attributePaths = {"members", "managers"})
Study findStudyWithManagersAndMembersById(Long id);
}
Study 엔티티에 있는 NamedEntityGraph 어노테이션을 모두 삭제 한다.
@NamedEntityGraph(name = "Study.withAll", attributeNodes = {
@NamedAttributeNode("tags"),
@NamedAttributeNode("zones"),
@NamedAttributeNode("managers"),
@NamedAttributeNode("members")})
@NamedEntityGraph(name = "Study.withTagsAndManagers", attributeNodes = {
@NamedAttributeNode("tags"),
@NamedAttributeNode("managers")
})
@NamedEntityGraph(name = "Study.withZonesAndManagers", attributeNodes = {
@NamedAttributeNode("zones"),
@NamedAttributeNode("managers")
})
@NamedEntityGraph(name = "Study.withManagers", attributeNodes = {
@NamedAttributeNode("managers")
})
@NamedEntityGraph(name = "Study.withMembers", attributeNodes = {
@NamedAttributeNode("members")
})
@NamedEntityGraph(name = "Study.withTagsAndZones", attributeNodes = {
@NamedAttributeNode("tags"),
@NamedAttributeNode("zones")
})
모두 삭제
StudyEventListener에 이벤트를 실행하는 로직인 handleStudyUpdateEvent메소드를 추가하고 기존의 중복코드를 제거하여 리팩토링한다.
package me.weekbelt.studyolle.modules.study.event;
@RequiredArgsConstructor
@Slf4j
@Async
@Transactional
@Component
public class StudyEventListener {
private final StudyRepository studyRepository;
private final AccountRepository accountRepository;
private final EmailService emailService;
private final TemplateEngine templateEngine;
private final AppProperties appProperties;
private final NotificationRepository notificationRepository;
@EventListener
public void handleStudyCreatedEvent(StudyCreatedEvent studyCreatedEvent) {
// Tags와 Zones를 참조할수 있는 Study를 가져왔다.
Study study = studyRepository.findStudyWithTagsAndZonesById(studyCreatedEvent.getStudy().getId());
Iterable<Account> accounts = accountRepository
.findAll(AccountPredicates.findByTagsAndZones(study.getTags(), study.getZones()));
accounts.forEach(account -> {
if (account.isStudyCreatedByEmail()) {
sendStudyCreatedEmail(study, account, "새로운 스터디가 추가되었습니다.",
"스터디올래, '" + study.getTitle() + "' 스터디가 생겼습니다."); // 추가
}
if (account.isStudyCreatedByWeb()) {
createNotification(study, account, study.getShortDescription(), NotificationType.STUDY_CREATED); // 수정
}
});
}
@EventListener
public void handleStudyUpdateEvent(StudyUpdateEvent studyUpdateEvent) {
Study study = studyRepository.findStudyWithManagersAndMembersById(studyUpdateEvent.getStudy().getId());
Set<Account> accounts = new HashSet<>();
accounts.addAll(study.getManagers());
accounts.addAll(study.getMembers());
accounts.forEach(account -> {
if (account.isStudyUpdatedByEmail()) {
sendStudyCreatedEmail(study, account, studyUpdateEvent.getMessage(),
"스터디올래, '" + study.getTitle() + "' 스터디에 새소식이 있습니다.");
}
if (account.isStudyUpdatedByWeb()) {
createNotification(study, account, studyUpdateEvent.getMessage(), NotificationType.STUDY_UPDATED);
}
});
}
// contextMessage, emailSubject 파라미터 추가
private void sendStudyCreatedEmail(Study study, Account account, String contextMessage, String emailSubject) {
Context context = new Context();
context.setVariable("nickname", account.getNickname());
context.setVariable("link", "/study/" + study.getEncodedPath());
context.setVariable("linkname", study.getTitle());
context.setVariable("message", contextMessage);
context.setVariable("host", appProperties.getHost());
String message = templateEngine.process("mail/simple-link", context);
EmailMessage emailMessage = EmailMessage.builder()
.subject(emailSubject) // 수정
.to(account.getEmail())
.message(message)
.build();
emailService.sendEmail(emailMessage);
}
// 매개변수 추가 message, nitificationType
private void createNotification(Study study, Account account, String message,
NotificationType notificationType) {
Notification notification = new Notification();
notification.setTitle(study.getTitle());
notification.setLink("/study/" + study.getEncodedPath());
notification.setChecked(false);
notification.setCreatedDateTime(LocalDateTime.now());
notification.setMessage(message); // 수정
notification.setAccount(account);
notification.setNotificationType(notificationType); // 수정
notificationRepository.save(notification);
}
}
참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#
'스프링과 JPA 기반 웹 어플리케이션 개발 > 7부 알림' 카테고리의 다른 글
77. 모임 관련 알림 (0) | 2020.05.12 |
---|---|
75. 알림 목록 조회 및 삭게 (0) | 2020.05.12 |
74. 스터디 알림 아이콘 변경 (0) | 2020.05.12 |
73. 스터디 개설 알림 (0) | 2020.05.11 |
72. 알림 처리 설계 (0) | 2020.05.11 |