MappingJacksonJsonView에 취소선이 가있었다. 이것이 삽질의 계기였다.

소스코드에서는 Jackson2로 이동해달라는 요청이 있길래 넘어갔다.

그런데 이게... 생각보다 여파가 컸다...

가장 큰 놈이... spring-data-redis.

이 녀석은 아직 Jackson2RedisSerializer가 없어서 Jackson과 Jackson2를 프로젝트에 함께 사용해야하는 문제가 있다.

spring-data-redis 1.2.0이 나올 때까지는 Jackson2로 갈아엎는 것은 보류다.

구글 SMTP를 사용하다가, 고객의 요구에 따라 네이버나 다음으로 변경하려고 했는데...
smtp 로 메일 발송테스트를 하는데 포트만 바꾸면 될 줄 알았더니... 아니더라.
상당한 삽질을 통해 확인한 결과는 다음과 같다.

application.properties

mail.host = smtp.gmail.com
mail.port = 587
mail.protocol = smtp

mailService 빈설정

<bean class="...MailServiceImpl">
        <constructor-arg name="mailSender">
            <bean class="org.springframework.mail.javamail.JavaMailSenderImpl"
                  p:password="${mail.password}"
                  p:host="${mail.host}"
                  p:port="${mail.port}"
                  p:protocol="${mail.protocol}"
                  p:username="${mail.username}"
                  p:defaultEncoding="${mail.encoding}">
                <property name="javaMailProperties">
                    <props>
                        <prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable}</prop>
                        <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
                    </props>
                </property>
            </bean>
        </constructor-arg>
    </bean>

네이버 메일 테스트 시

mail.xml 파일의 MailServiceImpl 빈 설정을

<bean class="...impl.MailServiceImpl">
    <constructor-arg name="mailSender">
        <bean class="org.springframework.mail.javamail.JavaMailSenderImpl"
            p:password="${mail.password}" p:host="${mail.host}" p:port="${mail.port}"
            p:protocol="${mail.protocol}" p:username="${mail.username}"
            p:defaultEncoding="${mail.encoding}">
            <property name="javaMailProperties">
                <props>
                    <prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable}</prop>
                    <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
                    <prop key="mail.smtps.ssl.checkserveridentity">true</prop>
                    <prop key="mail.smtps.ssl.trust">*</prop>
                </props>
            </property>
        </bean>
    </constructor-arg>
</bean>

의 형태로 변경한다. 기존 설정내용과의 차이는

<prop key="mail.smtps.ssl.checkserveridentity">true</prop>
<prop key="mail.smtps.ssl.trust">*</prop>

그리고 application.properties의 내용을 다음과 같이 변경한다.

mail.host = smtp.naver.com
mail.port = 465
mail.protocol = smtps

테스트를 위해서 작성된 MailServiceImplTest를 실행하여 확인하다.
테스트를 실행하기 위해서는 MailServiceImplTest-context.xml 의 내용을 다음과 같이 변경하시고,

<bean class="...MailServiceImpl">
    <constructor-arg name="mailSender">
        <bean class="org.springframework.mail.javamail.JavaMailSenderImpl"
            p:password="${mail.password}" p:host="${mail.host}" p:port="${mail.port}"
            p:protocol="${mail.protocol}" p:username="${mail.username}"
            p:defaultEncoding="${mail.encoding}">
            <property name="javaMailProperties">
                <props>
                    <prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable}</prop>
                    <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
                    <prop key="mail.debug">true</prop> <!-- 이건 테스트를 위한 디버그 내용 확인을 위한 겁니다.  -->
                    <prop key="mail.smtps.ssl.checkserveridentity">true</prop>
                    <prop key="mail.smtps.ssl.trust">*</prop>
                </props>
            </property>
        </bean>
    </constructor-arg>
</bean>

test의 setFrom의 메일 계정은 로그인에 사용된 계정과 동일하게 변경한다.


다음 메일 SMTP 테스트 시

daum으로 발송할 경우에는, MailServiceImplTest 를 다음과 같이 변경하고

<bean class="...MailServiceImpl">
    <constructor-arg name="mailSender">
        <bean class="org.springframework.mail.javamail.JavaMailSenderImpl"
            p:password="${mail.password}" p:host="${mail.host}" p:port="${mail.port}"
            p:protocol="${mail.protocol}" p:username="${mail.username}"
            p:defaultEncoding="${mail.encoding}">
            <property name="javaMailProperties">
                <props>
                    <prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable}</prop>
                    <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
                    <prop key="mail.debug">true</prop> <!-- 이건 테스트를 위한 디버그 내용 확인을 위한 겁니다.  -->
                </props>
            </property>
        </bean>
    </constructor-arg>
</bean>

application.properties

mail.host = smtp.daum.net
mail.port = 465
mail.protocol = smtps

메일을 발송할 때에는, from 이메일 주소는 로그인에 사용된 메일주소와 동일해야 한다. protocol이 smtp가 아니라 smtps 이다. JavaMail에서 접근방식이 다를 줄은 몰랐다.

protocol이 'smtps'여야 SSL 설정이 활성화된다.

별도의 설정 프로퍼티가 있을 줄 알았는데... 크흐.


Aspect Logger Sample

package com.sil.docsflow.common.support.spring;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created with IntelliJ IDEA.
 *
 * @author: ihoneymon
 * Date: 14. 1. 10
 */
public class AspectLogger {
    private static final Logger logger = LoggerFactory.getLogger(AspectLogger.class);

    public void afterThrowingAdvice(JoinPoint joinPoint, Throwable exception) {
        String signatureInfo = getSignatureInfo(joinPoint);
        String exceptionMessage = exception.getMessage();
        if (exceptionMessage == null || exceptionMessage.trim().length() < 1) {
            exceptionMessage = "oops! occured exception";
        }

        logger.debug("=>> ### " + signatureInfo + " : " + exceptionMessage, exception);
        logger.warn("<<= ### " + signatureInfo + " : " + exceptionMessage);
    }

    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        String signatureInfo = getSignatureInfo(joinPoint);

        logger.debug("=>> " + signatureInfo);
        Object retVal = joinPoint.proceed();
        logger.debug("<<= " + signatureInfo + (retVal != null ? " : " + retVal : ""));

        return retVal;
    }

    private String getSignatureInfo(JoinPoint joinPoint) {
        String signatureName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getSimpleName();

        StringBuilder sb = new StringBuilder();
        sb.append(className).append('.').append(signatureName).append('(');

        Object[] args = joinPoint.getArgs();
        if (args != null && args.length > 0) {
            for (int i = 0; i < args.length; i++) {

                if (args[i] instanceof String) sb.append('\"');
                sb.append(args[i]);
                if (args[i] instanceof String) sb.append('\"');

                if (i < args.length - 1) {
                    sb.append(',');
                }
            }
        }
        sb.append(')');

        return sb.toString();
    }
}

일반적으로 사용가능한 Aspect Logger.

이를 사용하기 위한 logging.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <aop:aspectj-autoproxy/>

    <bean id="loggingAspect" class="{package}.AspectLogger"/>
    <aop:config>
        <aop:aspect ref="loggingAspect">
            <aop:pointcut id="loggingPointCut" expression="execution(* {package}.{class}({method})) $amp;$amp; !execution(* {package}.AopLogger(..))"/>
            <aop:around method="aroundAdvice" pointcut-ref="loggingPointCut"/>
            <aop:after-throwing method="afterThrowingAdvice" pointcut-ref="loggingPointCut" throwing="exception"/>
        </aop:aspect>
    </aop:config>
</beans>

위의 설정에서 빼먹지 말 것은, <aop:pointcut id="loggingPointCut" expression="execution(* {package}.{class}({method})) $amp;$amp; !execution(* {package}.AopLogger(..))"/> 에서 !execution 이다. AspectLogger 자신을 포인트컷에서 제외시켜주어야 한다. 다른 곳에서는 별다른 문제가 없었는데… 지금 개발하고 있는 프로젝트에서 끊임없이 자신을 물고 들어가면서 로그를 찍다가 예외들을 뱉는다. 그래서 묻어두었다가 logger를 입력하는 것이 귀찮아서 다시 AspectLogger를 꺼내어 들었다.

intellij 12.1.5 버전에서 컴파일과 관련한 문제로 Lombok이 제대로 동작하지 않는 기현상을 보였다. 이에 jetbrain에서는 급히 컴파일 문제를 해결한 12.1.6 으로 업그레이드버전을 제공했다. 그런데 이녀석으로 업그레이드를 한 이후에 계속 컴파일 중에 오류가 발생한다.


로그에서 'ajc: the method ...' 라고 하는 메시지를 출력하며, Lombok annotation을 사용한 클래스가 정상적으로 컴파일 되지 않았다.

Lombok의 annotation이 컴파일시에 제대로 동작하지 않아서 생기는 문제가 아닐까 하고 Lombok plugin 재설치를 몇번해보고 설정에서 Compiler - Annotation Processors 에서 'Enable annotation processing'을 체크했다가 해제했다가를 반복했지만 증상은 똑같았다.

인터넷 검색을 해도 딱히 답이 나오지 않던 상황...

불현듯 '컴파일러!' 가 떠오르면서 'Compiler - Java Compiler' 를 찾아 들어갔다. 

'Use Compiler' 에 보니까 내가 모르는 Ajc가 선택되어 있다.

컴파일러를 'javac' 로 변경하고 나니 정상적으로 컴파일되고 배포까지 완료되었다...!! 두둥!

로그 속에 답이 있다는 진리를 새삼 깨닫다.


 

 정리

 

Intellij 12.1.6 업그레이드 후에도 Lombok 이 정상동작 하지 않을 시,

  • 이동: [Settings...] - [Compiler] - [Java Compiler]
  • 변경: 'User Compiler' - javac 로 변경



... Default는 javac라면서? 난... Compiler 변경한 적 없다!!

참여링크 : http://onoffmix.com/event/19279

다른 분들과 함께 열심히 준비중인 컨퍼런스가 열립니다. ^^ 많은 참여 부탁드립니다.


+ Recent posts