Whiteship's Note


[봄싹] 메일 서비스를 알림 서비스로 통합하기

모하니?/Coding : 2009.10.20 21:23




알림 서비스는 현재 구글 토크와 트위터에 스터디와 모임 소식을 전달해주고 있습니다. 그런데 이전에 만든 메일 서비스가 이 것과 굉장히 비슷한 구조였습니다.


녹색은 스프링에서 제공하는 라이브러리이고, 파란색 계열이 봄싹 코드입니다. 보시면 알림 서비스와 거의 같은 구조지만, 사용하는 클래스가 조금 다르고, SendMailService가 구현하는 인터페이스가 없다는 것만 다를 뿐입니다.

이 두 개의 서비스를 사용하는 NotificationAspect를 보면 통합의 필요성을 더 확실하게 느낄 수 있습니다.

@Aspect
public class NotificationAspect {
  
    @Autowired SendMailService sendMailService;
    @Autowired JabberService messangerService;
    @Autowired TwitterService twitterService;
    @Autowired MemberService memberService;
...
    @AfterReturning(pointcut = "addStudyPointcut() && args(study)", argNames="study")
    public void sendMailAfterAddStudy(Study study){
        sendMailService.sendMail(new StudyMail(study, StudyStatus.OPEN, memberService.getMemberList()));
        StudyMessage msg = new StudyMessage(study, StudyStatus.OPEN, memberService.getMemberList());
        messangerService.sendMessage(msg);
        twitterService.sendMessage(msg);
    }
...

    @AfterReturning(pointcut = "addMeetingPointcut() && args(study, meeting)", argNames="study, meeting")
    public void sendMailAfterAddMeeting(Study study, Meeting meeting){
        sendMailService.sendMail(new MeetingMail(study, meeting, MeetingStatus.OPEN));
        MeetingMessage msg = new MeetingMessage(study, meeting, MeetingStatus.OPEN);
        messangerService.sendMessage(msg);
        twitterService.sendMessage(msg);
    }
}

sendMailService도 다른 알림 서비스와 같은 인터페이스를 구현하고, SpringSproutMessage 타입의 객체를 받아서 사용할 수 있다면. 어떤 일이 벌어질지 보이시나요?

저에게는 콜렉션이 보이고, 애스팩트의 여러 어브다이스에서 연달아 메서드를 호출해주는 구조의 중복을 제거할 수 있어 보입니다.

그래서 통합했습니다.


메시지쪽이 좀 까다로웠지만, 상속을 이용해서 나름 열심히 작업했습니다.

결과는 어떨까요?
1. 메시지 작성이 간편해졌습니다.
2. NotificationAspect가 다이어트를 했습니다.

원했던 성과를 거뒀습니다.

    <util:list id="notificationServices">
        <value>sendMailService</value>
        <value>jabberService</value>
        <value>twitterService</value>
    </util:list>

이렇게 빈 설정을 해 놓고..

@Aspect
public class NotificationAspect {
  
    @Autowired List<NotificationService> notificationServices;
    @Autowired MemberService memberService;

...

    @AfterReturning(pointcut = "addStudyPointcut() && args(study)", argNames="study")
    public void sendMailAfterAddStudy(Study study){
        sendMsg(new StudyMailMessage(study, StudyStatus.OPEN, memberService.getMemberList()));
    }

    @AfterReturning(pointcut = "addMeetingPointcut() && args(study, meeting)", argNames="study, meeting")
    public void sendMailAfterAddMeeting(Study study, Meeting meeting){
        sendMsg(new MeetingMailMessage(study, meeting, MeetingStatus.OPEN));
    }

    private void sendMsg(SpringSproutMessage msg) {
        for(NotificationService service : notificationServices)
            service.sendMessage(msg);
    }

...
}

NotificationAspect 코드를 이렇게 리팩토링 했습니다.

캬~~~ 엄청난 대규모 리팩토링이었는데 생각했던대로 되서 다행입니다. 이 작업을 진행하는 내내 테스트가 충분하지 않아서 굉장히 불안했었는데, 그래도 최소한의 테스트가 마지막 검증을 하는데 도움이 됐습니다. 역시.. 테스트는 있어야 합니다. 매우 필요한 존재에요;

다음 과제는 모임 등록시 SWF 적용하기!!

top


[지름신 물럿거라] 누워서 노트북하기. Liadback



오랜만에 찾아온 지름신. 제품은 100달러인데 배송비가 40달러구나. 너무한거 아니니...

http://cgi.ebay.com/Laptop-Laidback-Table-portable-ergonomic-computing_W0QQitemZ280352012044QQcmdZViewItemQQptZLH_DefaultDomain_0?hash=item414648370c

침대에 누워서 책을 보거나 노트북을 하면, 목이 아프거나, 허리가 아프거나, 무릎이 뜨겁고, 팔이 아프고,
침대에 엎드려서 하면 목 아프고 어깨가 결리죠.



그래서 찾다가 이녀석을 발견했지만, 배송비가 너무 비싸서 포기~.

이것보다 좀 더 가볍고 미려하게 생겼으면서 가격도 싸고 쓸만해 보이는게 있으면 좋겠습니다.
top

TAG Liadback

[리팩토링] 메일을 메시지로 통합하기

모하니?/Coding : 2009.10.20 00:11


이메일 서비스를 알림 서비스쪽으로 통합중입니다. 서비스 클래스를 통합하는 건 간단했습니다.

@Service
public class SendMailService implements NotificationService{
   
    @Autowired JavaMailSender mailSender;

    public void sendMessage(SpringSproutMessage ssm) {
        SpringSproutMail mail = (SpringSproutMail)ssm;
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, SpringSprout2System.ENCODING);
        try {
            helper.setTo(mail.getRecievers());
            helper.setFrom(mail.getFrom());
            helper.setSubject(mail.getSubject());
            helper.setText(mail.getContent(), mail.isHTML());
        } catch (MessagingException e) {
            throw new MailPreparationException(e);
        }
        mailSender.send(message);
    }

}

NotificationService를 구현하기만 하면 끝이죠. 그런데 문제는 이제부터 시작이었습니다. SpringSproutMessage.. 이 녀석을 받아서 메시지를 보내도록 해야하는데, SendMailService는 기존에 SpringSproutMail을 상속받아 만든 Mail 클래스들을 받아서 사용하고 있었습니다.

SSMessage와 SSMail은 상당부분 비슷한 속성과 메서드가 있으면서도 메시지 내용 상으로는 다소 차이가 있었습니다. 구글 토크나 트위터에는 간단한 메시지와 링크주소만 보내지만, 이메일로는 좀 더 구체적인 정보들까지 HTML 형태로 보내기 때문이죠.

public class SpringSproutMail extends SpringSproutMessage {
   
    public static final String SUBJECT_PREFIX = "[봄싹]";
    public static final String SENDER_MAIL = "s2cmailer@gmail.com";
   
    private String subject;
    private String content;
    private String[] recievers;
    private String from;
    private boolean isHTML;
   
    public SpringSproutMail() {
        this.from = SENDER_MAIL;
        this.isHTML = true;
    }
   
  ...
   
    protected void setTo(Member member) {
        String[] tos = new String[1];
        tos[0] = member.getEmail();
        setRecievers(tos);
    }
   
    protected void setTo(Collection<Member> members) {
        String[] recievers = new String[members.size()];
        Iterator<Member> memberIterator = members.iterator();
        for(int i = 0 ; i < recievers.length ; i++){
            recievers[i] = memberIterator.next().getEmail();
            tos.add(recievers[i]);
        }
        setRecievers(recievers);
    }
   
}

일단은 Mail 쪽의 최상위 클래스인 SpringSproutMail이 SpringSproutMessage를 상속받도록 수정했습니다. 그랬더니 아무 문제없이 잘 돌아가더군요. 이상태에서 일단 정지입니다. 돌아가게 만든 상태에서 어떻게 리팩토링 해야할지 고민좀 해야겠습니다.
top