티스토리 뷰

[WARN ][o.s.w.s.m.s.DefaultHandlerExceptionResolver.logException:line199] - Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class java.util.LinkedHashMap]

REST API 샘플을 만들다가 응답과정에서 위와 같은 오류를 만났다. No converter found for return value of type !

왜 이런 오류가 났는지 알아보도록 하자. 


Controller의 모습은 일반적인 REST API의 모습과 거의 같다. 

Controller

@RestController
public class MessageController {
	
    @Autowired
    private MessageService messageService;

    @GetMapping(value = "/message")
    public OingData getMessageList() {
        return messageService.getMessageList();
    }
    
    @GetMapping(value = "/message/{messageText}")
    public OingData getMessage(@PathVariable String messageText) {
        return messageService.getMessage(messageText);
    }

    @PostMapping(value = "/message")
    public OingData saveMessage(OingData oingData) {
        return messageService.saveMessage(oingData);
    }
}

@Controller를 @RestController로 정의하였고 이에 따라 모든 응답은 @ResponseBody 형태이다. 

OingData라는것을 만들어서 데이터를 주고 받는 표준을 정했다. 이를 위해 OingData를 구성하기 위한 ArgumentResolver를 만들었고 이에 대한 설정을 다음과 같이 하였다. 

 

WebConfig

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
       
    @Bean
    public CustomRequestMappingHandlerAdapter customRequestMappingHandlerAdapter() {
        CustomRequestMappingHandlerAdapter adapter = new CustomRequestMappingHandlerAdapter();
        adapter.setCustomArgumentResolver(customArgumentResolver());
        return adapter;
    }
    
    @Bean 
    public CustomArgumentResolver customArgumentResolver() {
        return new CustomArgumentResolver();
    }
}

@EnableWebMvc는 사용하지 않고 WebMvcConfigurationSupport를 상속받아서 WebConfig를 구성하였다. 이에 따라 CustomRequestMappingHandlerAdapter를 만들어서 CustomArgumentResolver를 등록한 상태이다. 이렇게 하고 Request를 날려 보니 응답이 정상적으로 이루어지지 않고 No converter found for return value of type 가 발생하였다. 

 

응답을 정상적으로 하게 하려면 @EnableWebMvc를 WebConfig에 넣으면 되긴 한다. 하지만 이랬을 경우는 위에서 설정한 ArgumentResolver가 동작하지 않는 문제가 있었다. OingData라는 data를 정상적으로 받아볼 수 없었다. 그래서 다시 @EnableWebMvc를 빼고 위의 로직(WebConfig)에 다음을 추가하여 문제를 해결하였다. 

 

private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();

@PostConstruct
public void initStuff() {
    List<HttpMessageConverter<?>> messageConverters = this.customRequestMappingHandlerAdapter().getMessageConverters();
    messageConverters.clear();

    GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();
    gsonHttpMessageConverter.setGson(GSON);
    messageConverters.add(gsonHttpMessageConverter);

    StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
    stringHttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8);
    messageConverters.add(stringHttpMessageConverter);

    this.customRequestMappingHandlerAdapter().setMessageConverters(messageConverters);
}

참고 : blog.naver.com/bestheroz/221327093778

 

RequestMappingHandlerAdapter에 messageConverter를 추가해줘야한다. 위처럼 하지 않고 그냥 일반적으로 messageConverter를 bean으로 등록한다면 아마 안될 것이다. 적어도 RequestMappingHandlerAdapter를 Custom 하여 사용하고 있다면 위와 같은 방식으로 해줘야 한다. 우리에게 익숙한 Jackson을 사용하지 않고 Gson을 사용하여 Converter를 구성하였다. 물론 Gson을 이용하기 위해서는 다음과 같이 dependency 추가가 필요하다. 

 

pom.xml

(spring-boot-starter를 사용중이면 내장되어 있으므로 별도의 설정은 필요 없다.)

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

 

끝!

 

 

댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31