1. 개요

이 튜토리얼에서 우리는 Spring의 HttpMessageNotWritableException : "No converter found for return value of type" 예외에 대해 설명 할 것입니다.

먼저 예외의 주요 원인을 설명하겠습니다. 그런 다음 실제 예제를 사용하여 생성하는 방법과 마지막으로 수정하는 방법을 자세히 살펴 보겠습니다.

2. 원인

일반적으로이 예외는 Spring이 반환 된 객체의 속성을 가져 오지 못할 때 발생합니다.

이 예외의 가장 일반적인 원인은 일반적으로 반환 된 객체에 해당 속성에 대한 공개 getter 메서드가 없기 때문 입니다.

기본적으로 Spring Boot는 Jackson 라이브러리 에 의존하여 요청 및 응답 객체를 직렬화 / 역 직렬화하는 모든 작업을 수행합니다.

따라서 예외의 또 다른 일반적인 원인은 누락되거나 잘못된 Jackson 의존성을 사용하는 것 입니다.

요컨대, 이러한 예외에 대한 일반적인 지침은 다음이 있는지 확인하는 것입니다.

  • 기본 생성자
  • 게터
  • Jackson 의존성

것을 명심하시기 바랍니다 예외 유형이 변경되었습니다 java.lang.IllegalArgumentException가org.springframework.http.converter.HttpMessageNotWritableException.

3. 실제 사례

이제 org.springframework.http.converter.HttpMessageNotWritableException 을 생성하는 예제를 살펴 보겠습니다 . "No converter found for return value of type".

실제 사용 사례를 보여주기 위해 Spring Boot를 사용하여 학생 관리를위한 기본 REST API를 빌드 할 것 입니다.

먼저 모델 클래스 Student를 만들고 getter 메서드를 생성하는 것을 잊은 척 합시다 .

public class Student {

    private int id;
    private String firstName;
    private String lastName;
    private String grade;

    public Student() {
    }

    public Student(int id, String firstName, String lastName, String grade) {
	this.id = id;
	this.firstName = firstName;
	this.lastName = lastName;
	this.grade = grade;
    }

    // Setters
}

둘째, IDStudent 객체 를 검색하는 단일 핸들러 메소드로 Spring 컨트롤러생성합니다 .

@RestController
@RequestMapping(value = "/api")
public class StudentRestController {

    @GetMapping("/student/{id}")
    public ResponseEntity<Student> get(@PathVariable("id") int id) {
        // Custom logic
        return ResponseEntity.ok(new Student(id, "John", "Wiliams", "AA"));
     }
}

이제 CURL을 사용하여 http : // localhost : 8080 / api / student / 1에 요청을 보내면 :

curl http://localhost:8080/api/student/1

엔드 포인트는 다음 응답을 다시 보냅니다.

{"timestamp":"2021-02-14T14:54:19.426+00:00","status":500,"error":"Internal Server Error","message":"","path":"/api/student/1"}

로그를 보면 Spring은 HttpMessageNotWritableException을 던졌습니다 .

[org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.baeldung.boot.noconverterfound.model.Student]

마지막으로 Student 클래스 에 getter 메서드가 정의되어 있지 않을 때 Spring이 어떻게 동작하는지 확인하기위한 테스트 케이스를 생성 해 보겠습니다 .

@RunWith(SpringRunner.class)
@WebMvcTest(StudentRestController.class)
public class NoConverterFoundIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void whenGettersNotDefined_thenThrowException() throws Exception {

        String url = "/api/student/1";

	this.mockMvc.perform(get(url))
	  .andExpect(status().isInternalServerError())
	  .andExpect(result -> assertThat(result.getResolvedException())
            .isInstanceOf(HttpMessageNotWritableException.class))
	  .andExpect(result -> assertThat(result.getResolvedException().getMessage())
	    .contains("No converter found for return value of type"));
    }
}

4. 해결책

예외를 방지 하는 가장 일반적인 솔루션 중 하나는 JSON으로 반환하려는 각 객체의 속성에 대해 getter 메서드를 정의하는 것입니다.

따라서 Student 클래스 에 getter 메서드를 추가하고 모든 것이 예상대로 작동하는지 확인하는 새 테스트 케이스를 만들어 보겠습니다.

@Test
public void whenGettersAreDefined_thenReturnObject() throws Exception {

    String url = "/api/student/2";

    this.mockMvc.perform(get(url))
      .andExpect(status().isOk())
      .andExpect(jsonPath("$.firstName").value("John"));
}

잘못된 해결책은 부동산을 공개하는 것입니다. 그러나 이것은 몇 가지 모범 사례에 위배되므로 100 % 안전한 접근 방식은 아닙니다.

5. 결론

이 짧은 기사에서 우리는 Spring이 org.springframework.http.converter.HttpMessageNotWritableException 을 던지는 원인을 설명했습니다 :”No converter found for return value of type” .

그런 다음 예외를 생성하는 방법과 실제로 처리하는 방법에 대해 논의했습니다.

항상 그렇듯이 예제의 전체 소스 코드는 GitHub에서 사용할 수  있습니다 .