ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring/Java - ModelMapper 사용시 Source Object null 케이스 처리 방법
    Spring 2020. 2. 13. 16:47

    ModelMapper는 Entity <-> DTO 간 객체 전환 및 매핑 반복작업 작업을 줄여주는 라이브러리다.

     

    이를 간편하게 Spring에서 사용하려면 다음과 같이 ModelMapper를 bean으로 등록하고 필요한 부분에서 DI받아 사용하면 된다.

     

    # Bean 등록

    - MatchingStrategies.STRICT : source와 target의 같은 타입+타입명 일때 변환 처리하는 옵션

    ( 디테일 옵션 정보 : http://modelmapper.org/user-manual/configuration/#matching-strategies )

    @Configuration
    public class ModelMapperConfig {
    	@Bean
    	public ModelMapper modelMapper() {
    		ModelMapper modelMapper = new ModelMapper();
    		
    		/*연결 전략 : 같은 타입의 필드명이 같은 경우만 동작*/
    		modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); 
    		return modelMapper;
    	}
    }

    # 사용 방법

    private final ModelMapper modelMapper;
    
    public SimpleService(final ModelMapper modelMapper){
    	this.modelMapper = modelMapper;
    }
    
    ...
    
    Target target;
    Source source;
    
    // source -> target object 로 변환 처리
    target = modelMapper.map(source, Target.class);

    여기서 만약 Source Object가 null 일 경우, 다음과 같은 익셉션이 발생 하게 된다.

    ( java.lang.IllegalArgumentException: source cannot be null )

    [Rest][2020-01-23 00:21:52][ERROR][DirectJDKLog.java][log(175)] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: source cannot be null] with root cause
    java.lang.IllegalArgumentException: source cannot be null
    	at org.modelmapper.internal.util.Assert.notNull(Assert.java:53)
    	at org.modelmapper.ModelMapper.map(ModelMapper.java:404
    ...

    이 경우에 실제 Source가 필수 적으로 필요한 경우에는 해당 익셉션 처리가 필요하며,

    만약 Source Object가 null인 경우에 Target Object가 default constructor 또는 특정 값으로 정의 시킬 경우, Modelmapper의 map 메소드를 오버라이드 하여 처리하면 된다.

     

    ModelMapper.map() 메소드 오버라이드 처리를 위해서는 CustomModelMapper 클래스를 생성하고 bean으로 등록 해주면 된다.

     

    # CustomModelMapper 생성

    /**
     * ModelMapper는 기본적으로 source class가 null인 경우에 throw exception을 발생 시킨다.
     * 그래서 해당 ModelMapper의 map 메소드를 오버라이드 해서, 기본 오브젝트로 생성 되도록 처리
     *
     */
    public class CustomModelMapper extends ModelMapper {
    
        @Override
        public <D> D map(Object source, Class<D> destinationType) {
            Object tmpSource = source;
            if(source == null){
                tmpSource = new Object();	// 기본 생성자로 생성 처리
            }
    
            return super.map(tmpSource, destinationType);
        }
    
    }
    

    # CustomModelMapper Bean 등록

    @Configuration
    public class ModelMapperConfig {
    	@Bean
    	public ModelMapper modelMapper() {
    		ModelMapper modelMapper = new CustomModelMapper();
    		
    		/*연결 전략 : 같은 타입의 필드명이 같은 경우만 동작*/
    		modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); 
    		return modelMapper;
    	}
    }
    

    ModelMapper.map() 메소드를 오버라이드 처리한 CustomModelMapper를 bean으로 등록하여 위에 설명한 사용법을 사용하면, Source Object 가 null 일 경우에도 Exception 없이 Target Object를 얻어 낼 수 있다.

     

    추가적으로 ModelMapper는 리플렉션 기반으로 동작하기에 성능 이슈가 존재하므로, Lombok 처럼 컴파일 시점에 생성해주는 Mapstruct를 사용하는 것도 좋으니 참고 바랍니다.

    ( 성능 비교 : https://www.baeldung.com/java-performance-mapping-frameworks )

     

    #참조 : https://stackoverflow.com/questions/37971193/modelmapper-how-to-apply-custom-mapping-when-source-object-is-null

Designed by Tistory.