Dozer Custom-Converter 사용법


최근 DTO(Data Transfer Object) 를 적용하면서 Dozer라는 자바 라이브러리를 알게되었다. ( DTO를 혹시 모른다면 이 글 [1]을 추천합니다)

Dozer란?

http://dozer.sourceforge.net/ 우리가 흔히 불도저로 알고 있는 그 도저다. ( 그냥 밀어버린다는 건가? )

Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to another.

쉽게 말해, 자바 빈을 다른 자바 빈에 매핑을 시켜주는 라이브러리이다. Hibernate Object를 DTO로 매핑 시켜야 할 때, 편리하게 사용할 수 있다.

문법도 간단해서 금방 적용시키기 쉽다. 우선 pom.xml 혹은 gradle.build 에 추가해주고

<dependency>
    <groupId>net.sf.dozer</groupId>
    <artifactId>dozer</artifactId>
    <version>5.4.0</version>
</dependency>
compile("net.sf.dozer:dozer:5.4.0")

다음과 같이 매핑시켜 줄 수 있다.[3]

Mapper mapper = new DozerBeanMapper();
DestinationObject destObject =
 mapper.map(sourceObject, DestinationObject.class);

(본 글은 Custom-Converter를 설명하고자 하기 때문에 자세한 내용은 생략!)

이렇게 쉬운 문법이다보니 남용하고 있는데… 어김없이 문제가 타나났다.

문제발생

내가 하고 있는 프로젝트에서는 joda-time 을 사용하고 있는데 mapping 후에는 계속 현재의 시간으로 바뀌는 문제가 있었다. 스택오버플로우 검색 결과[2] Dozer 내부에서 DateTime를 new DateTime() 으로 새로 생성하기때문에, 기존 데이터를 덮어씌워버리는 문제가 있다.

이를 해결하기위해 Custom Converter를 설정해보겠다.[4]

본 글에서는 Spring boot + maven을 사용해본다.

Dozer Custom Converter를 설정

1.pom.xml 에 dozer와 joda-time 추가

pom.xml

        <dependency>
            <groupId>net.sf.dozer</groupId>
            <artifactId>dozer</artifactId>
            <version>5.4.0</version>
        </dependency>

        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.8.2</version>
        </dependency>

2.오브젝트(Source와 Destination) 추가

EmployeeA.java

import org.joda.time.DateTime;

public class EmployeeA {

    String firstName;

    String lastName;

    DateTime birthday;

}

EmployeeB.java

import org.joda.time.DateTime;

public class EmployeeB {

    String firstName;

    String lastName;

    DateTime birthday;
}

3.dozerConfig 추가

@Configuration
public class dozerConfig {

    @Bean(name = "org.dozer.Mapper")
    public DozerBeanMapper dozerBean() {
        List<String> mappingFiles = Arrays.asList(
                 "dozer-configration-mapping.xml"
        );

        DozerBeanMapper dozerBean = new DozerBeanMapper();
        dozerBean.setMappingFiles(mappingFiles);
        return dozerBean;
    }

}

4.dozer-configration-mapping.xml

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozer.sourceforge.net
          http://dozer.sourceforge.net/schema/beanmapping.xsd">

    <configuration>
        <custom-converters>
            <converter
                    type="demo.DateTimeCustomConverter">
                <class-a>org.joda.time.DateTime</class-a>
                <class-b>org.joda.time.DateTime</class-b>
            </converter>
        </custom-converters>
    </configuration>

</mappings>

5.적용!

@Autowired
DozerBeanMapper dozerBeanMapper;

static Mapper mapper = new DozerBeanMapper();

@RequestMapping("/test")
public EmployeeB test(){
        EmployeeA employeeA = new EmployeeA();
        employeeA.setBirthday(new DateTime("2012-08-10"));

//        EmployeeB employee = mapper.map(employeeA, EmployeeB.class); // (1) 기본 DozerBeanMapper
        EmployeeB employee = dozerBeanMapper.map(employeeA, EmployeeB.class); // (2) Custom-Converter가 적용된 DozerBeanMapper

        return employee;
}

localhost:8080/test 를 접속해 실제로 잘 적용 되었는지를 확인 할 수 있다. (1) 주석을 풀고 다시 빌드해보면 기본 Dozer에서 joda time to joda time이 안되는 문제도 볼 수 있다.

위 내용은 아래 github에서 소스를 다운 받아 볼 수 있습니다. https://github.com/jiyeonseo/springboot-dozer-sample

참고 아티클