프로젝트 팀 도메인에 @PreAuthorize를 적용하려고 테스트를 해보던 중, 500 에러가 떴다.
java.lang.NullPointerException: Cannot invoke "java.lang.Boolean.booleanValue()" because the return value of "backend.techeerzip.domain.projectTeam.dto.request.TeamData.getIsRecruited()" is null
Boolean 자료형의 모집 여부, 진행 완료 여부를 표시하기 위한 isRecruited, isFinished 필드가 있고, getIsRecruited()를 호출해서 값을 가져왔더니 null이었다. 여기서 null을 boolean으로 바꾸려다가 에러가 났다.
찾아보니까 스프링부트에서 객체와 dto를 변환할 때 Jackson(JSON 파싱 라이브러리)을 쓰는데, JSON 데이터를 자바 객체로 변환할 때 클래스의 변수명이 아닌 Getter 메서드의 이름을 분석해서 사용한다고 한다.
public 메서드 스캔get이나 is로 시작하는 메서드 탐색 (Getter)get, is)를 제거하고 남은 단어의 첫 글자를 소문자로 바꾼 것을 JSON Key로 간주원래 getIsRecruited()에서 get을 제거하고 IsRecruited로 매핑되는 것이 맞지만, Jackson 라이브러리가 is로 시작하는 필드명에 대해 is 자체를 Getter의 접두사로 간주하고 한 번 더 제거해서 최종적으로 recruited라는 키를 찾으려다 매핑에 실패한 것이다.
| 타입 | 예시 | Getter 이름 | 특징 |
|---|---|---|---|
| Boolean (Wrapper) | private Boolean recruited; | public Boolean getRecruited() | 일반 객체(Object)와 똑같이 get 접두사 사용 |
| boolean (Primitive) | private boolean recruited; | public boolean getRecruited() | 기본형 boolean은 예외적으로 is 접두사 사용 |
그렇기 때문에 DTO에서 Boolean 타입 변수명 앞에 is를 붙이는 것을 피하거나 @JsonProperty로 명시하는 것이 안전하다.