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
}
둘째, ID 로 Student 객체 를 검색하는 단일 핸들러 메소드로 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” .
그런 다음 예외를 생성하는 방법과 실제로 처리하는 방법에 대해 논의했습니다.