항해99를 시작하기 전 구매해서 들었던 강의를 항해99에서 제공을 해줬다
그래서 똑같은 강의를 듣고있는데
아래와 같은 에러가 나는것이다..!
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.sparta.week02.domain.CourseRequestDto` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
강의를 직접 사서 들을 땐 이런 오류가 안 났었다
위의 글에 적혀있는 코드와 다른 점이 없다
다만 프로젝트를 다른 폴더(E드라이브)에다가 생성했다
이전에 블로그에 글을 적을 땐 기존 프로젝트는 InteliJ 설치할 때 생기는 IdeaProjects(C드라이브) 하위에서 진행했었다
나는 계속 이 점을 의심하고 있었지만, 그게 아닌 것 같았다..
우연히 Slack에 올라온 글을 보고 있었는데 나와 같은 내용을 질문한 사람이 있었다
2주차 강의 진행 중 CourseRequestDTO에서 final 필드를 이용하여 생성자를 만들경우POST 테스트에서 오류가 납니다
InvalidDefinitionException: Cannot construct instance of `com.sparta.week02.domain.CourseRequestDTO` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
생성자가 없다는 것 같은데 @RequiredArgsContructor가 final이 붙은 맴버들을 이용해 생성자를 만들어준다고 했는데요
해당 어노테이션과 final 필드를 없애고 기본 생성자와 모든 필드 생성자를 사용하니깐 POST 전송이 통과되었습니다
해당 강의 코드로 POST 전송이 통과하신분 있을까요? 아니면 저처럼 오류가 뜰까요?
위의 에러사항이 발생하는 사람들이 여럿 있나보다
에러를 질문한 사람이 댓글을 달았다
final을 때니깐 정상작동 하네요, 다른 책이나 강의 예제에서도 한번도 dto에 final을 붙인걸 본적이 없는데 이유가 궁금합니다!
이게 어차피 final을 붙이면 해당 필드들에 대해서 생성자가 생기게 되니깐 결과적으론 두 코드가 같은게 아닌가요?
멘토님이 이에 대한 답변을 해주셨다
final이 선언되어 있는 필드에 대해서는 초기화가 불가능하기 때문에 @NoArgsConstructor가 생성자를 만들 수 없습니다~! 그래서 final을 지우면 기본 생성자를 생성할 수 있게 되어요.
하지만 POST, PUT이 동작하려면 모든 필드에 대한 생성자가 필요하기 때문에 @AllArgsConstructor까지 붙여주어야 오류가 안 나는 것이 맞습니당!
그래서 @AllArgsConstructor를 제외하고 모든 필드를 활용한 생성자를 직접 아래의 코드처럼 만들어주어도 동일한 결과를 보여줍니다~!@NoArgsConstructor @Getter public class CourseRequestDto { private String title; private String tutor; public CourseRequestDto(String title, String tutor) { this.title = title; this.tutor = tutor; } }
아직도 이 글을 보고 완전히 이해한 것 같진 않다ㅠ
final을 쓰면 한번 초기화해준 값을 영원히 변경할 수 없는데,
현재는 final을 뺐으니 값을 수정할 수 있지 않은가..?
값을 수정 못하게하기 위해 final을 쓰는건데 그럼
update할 때 다른 사람이 데이터를 변경할 수 있으니 완충재로 사용을 한다는 DTO의 의미가 사라지지 않는가..?ㅠ
다른 멘토님이 댓글을 달아주셨다
안녕하세요 제가 추가적인 답변을 드린다면 일단 캡쳐로 알 수 있는 내용은 Dto에 기본 생성자가 없어서 실패한 에러 입니다. 질문자님의 기존 코드에는 requestDto의 필드 모두 final 필드로 지정했기 때문에 기본 생성자가 존재하지 않는 상태 입니다.
(final 필드로 선언하면 왜 기본 생성자가 없는지, final 필드의 초기화 시점은 언제인지에 등 관련된 내용에 대해서 추가적인 학습을 하시면 좋을것 같습니다.)
이제 그렇다면 왜 기본 생성자가 없을 때 해당 에러가 났는지 설명하겠습니다.
먼저 결론부터 말하면 Controller에서 Dto를 @RequestBody로 받을 때 ObjectMapper를 이용하는데 ObjectMapper가 serialize하는 과정에서 반드시 기본 생성자를 반드시 필요로 하기 때문에 발생했습니다.
이를 보다 자세히 이해하기 위해선 @ReqeustBody의 내부 동작원리를 자세알고 ObjectMapper에 대해서 보다 학습 하신다면 이해하실 수 있을 것입니다.
참고 자료 입니다.
https://velog.io/@conatuseus/RequestBody에-왜-기본-생정자는-필요하고-Setter는-필요-없을까-2-ejk5siejhh
안녕하세요, 질문자님과 같은 현상이신 분들은 아래 블로그를 참고해주시면 좋을 것 같습니다~
https://bbbicb.tistory.com/46
강의에서 final과 @RequiredArgsConstructor만으로도 정상 동작되니 헷갈리셨을 것 같은데요, 기존에 알고계신 것처럼
final 을 쓰지 않고 롬복 어노테이션을 통해 기본, All 생성자를 명시해주시는 것이 좋을 것 같습니다!ㅎㅎ
여기서 더 깊게 들어가면 spring bean 이랑 dependency injection이라는 개념이 나옵니다. spring에서 가장 중요한 개념이니 알아둬야해요
이 글도 참고해봐야될 것 같다
https://www.baeldung.com/jackson-deserialize-immutable-objects
수업에서 DTO에 final을 사용하여 기본생성자가 없는데도 불구하고 @Requestbody에서 ObjectMapping이 되어서 최근 젝슨라이브러리를 찾아봤는데 위 글처럼
@JsonCreator가 역직렬화를 지정된대상을 사용할 수 있도록 도와주는데 라이브러리가 스프링5,부트2내용이니까 버전업이되면서 자동으로 기본생성자가 없어도 매핑될 수 있도록 라이브러리에 담아져 있는거 아닐까요?
아직 구조를 정확히 이해못해서 정확히 테스트 해보지는 못했습니다.
내가 스프링 부트를 안 했을 동안 업데이트가 일어난것일까...
아직 잘 모르겠다...
위의 글들을 읽고 해결하긴 했다
수정 전 CourseRequestDto.java
package com.sparta.week02.domain;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@RequiredArgsConstructor
public class CourseRequestDto {
private final String title;
private final String tutor;
}
수정 후 CourseRequestDto.java
package com.sparta.week02.domain;
import lombok.*;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CourseRequestDto {
private String title;
private String tutor;
}
final을 떼고 @RequiredArgsConstructor를 지우고 @NoArgsConstructor와 @AllArgsConstructor를 추가해줬다
이렇게 수정해주니 정상 작동한다
'항해99 3기' 카테고리의 다른 글
[TIL] 2021.09.25 - 개인 프로젝트 요구 기능 완성 (0) | 2021.09.25 |
---|---|
[TIL] 2021.09.24 - Spring 강의 마무리, 개인 프로젝트 시작 (0) | 2021.09.24 |
[TIL] 2021.09.23 - Spring 3-4주차 강의 듣기 (0) | 2021.09.23 |
[TIL] 2021.09.22 - Spring 강의 2주차 듣기 (0) | 2021.09.23 |
[WIL] 항해99 3기 1주차 (0) | 2021.09.20 |