-
에러 기록 : rest api 응답시 도메인 객체의 id 필드 생략되는 경우에러기록 2023. 12. 17. 00:01
api 응답을
EntityModel<User>
타입으로 해주고 있었더니 @Id 어노테이션이 붙은 id 필드가 응답 결과에 출력되지 않았다.id 필드를 출력해주기 위해 다음 코드를 추가해 주고
MappingJacksonValue
타입으로 반환값을 변경해주니 원하는 형태로 응답 데이터가 출력되었다.MappingJacksonValue mapping = new MappingJacksonValue(entityModel); mapping.setFilters(null);
검색해도 원인을 찾지 못해서 chatGPT에 물어보니
Jackson은 객체를 직렬화할 때 @Id 어노테이션 또는 id 필드에 대해 특별한 처리를 하지 않는 경우, 기본적으로 id 필드를 출력하지 않도록 동작합니다.
라고 했다.
관련해서 설계되어있는 내용을 확인했다면 좋았을텐데 아직 알아내지 못했다.
구글링으로 id 필드에
@JsonIgnore(false)
를 추가하면 해결된다고 봤는데 나에겐 적용되지 않는 해결방안이었다.그리고 jackson으로 직렬화 하는 과정에 대해 디버깅을 해보고자 노력을 기울여보았지만 실패하고 말았다;
application.yml에서 logging 레벨도 조절해봤는데 로그를 볼 수 없었다. 😠
디버깅 포인트도 찍어보았는데 알아내지 못했다.
포인트를 잘못 짚었던걸지도 🫤
관련해서 더 조사해보고자 한다.알아내면 꼭 기록하러 다시 와야지 😡(내일)gg😣
+ Spring Boot 버전 2.7에서 경험한 에러라 혹시 3점대로 버전을 올리면 사라질까? 싶어서 3.1.5로 올려봤는데 그대로였다
원치않았던 결과 : User 객체의 id 필드만 생략 된 코드
@Slf4j @RequiredArgsConstructor @RequestMapping("/jpa") @RestController public class UserJpaController { private final UserRepository userRepository; @GetMapping("/users") public ResponseEntity<CollectionModel<User>> retrieveAllUsers() { List<User> users = userRepository.findAll(); UserJpaController methodOn = methodOn(this.getClass()); CollectionModel<User> model = CollectionModel.of(users); model.add(linkTo(methodOn.retrieveAllUsers()).withSelfRel().withType("GET")); model.add(linkTo(methodOn).slash("_id").withRel("info-user").withType("GET")); return ResponseEntity.ok(model); } @GetMapping("/users/{id}") public ResponseEntity<EntityModel<User>> retrieveUser(@PathVariable int id) { Optional<User> optionalUser = userRepository.findById(id); if (!optionalUser.isPresent()) throw new UserNotFoundException(String.format("없는 사용자 입니다. [id : %d]", id)); EntityModel<User> model = EntityModel.of(optionalUser.get()); model.add(linkTo(methodOn(this.getClass()).retrieveUser(id)).withSelfRel().withType("GET")); model.add(linkTo(methodOn(this.getClass()).retrieveAllUsers()).withRel("all-users").withType("GET")); return ResponseEntity.ok(model); } }
id 필드가 삭제된 응답 결과 - API GET "/users/{id}"
GET http://localhost:8088/jpa/users/1 HTTP/1.1 200 Content-Type: application/hal+json Transfer-Encoding: chunked Date: Wed, 25 Oct 2023 09:54:27 GMT Keep-Alive: timeout=60 Connection: keep-alive { "name": "zhyun1", "joinDate": "2023-10-25T18:54:22.185935", "password": "1111", "ssn": "701010-1111111", "_links": { "self": { "href": "http://localhost:8088/jpa/users/1", "type": "GET" }, "all-users": { "href": "http://localhost:8088/jpa/users", "type": "GET" } } } 응답 파일이 저장되었습니다. > 2023-10-25T185427.200.json Response code: 200; Time: 700ms (700 ms); Content length: 346 bytes (346 B)
원하던 결과 : User 객체의 id 필드가 출력되는 코드
@Slf4j @RequiredArgsConstructor @RequestMapping("/jpa") @RestController public class UserJpaController { private final UserRepository userRepository; @GetMapping("/users") public ResponseEntity<MappingJacksonValue> retrieveAllUsers() { List<User> users = userRepository.findAll(); UserJpaController methodOn = methodOn(this.getClass()); CollectionModel<User> model = CollectionModel.of(users); model.add(linkTo(methodOn.retrieveAllUsers()).withSelfRel().withType("GET")); model.add(linkTo(methodOn).slash("_id").withRel("info-user").withType("GET")); MappingJacksonValue mapping = new MappingJacksonValue(model); mapping.setFilters(null); return ResponseEntity.ok(mapping); } @GetMapping("/users/{id}") public ResponseEntity<MappingJacksonValue> retrieveUser(@PathVariable int id) { Optional<User> optionalUser = userRepository.findById(id); if (!optionalUser.isPresent()) throw new UserNotFoundException(String.format("없는 사용자 입니다. [id : %d]", id)); EntityModel<User> model = EntityModel.of(optionalUser.get()); model.add(linkTo(methodOn(this.getClass()).retrieveUser(id)).withSelfRel().withType("GET")); model.add(linkTo(methodOn(this.getClass()).retrieveAllUsers()).withRel("all-users").withType("GET")); MappingJacksonValue mapping = new MappingJacksonValue(model); mapping.setFilters(null); return ResponseEntity.ok(mapping); } }
id 필드가 포함된 응답 결과 - API GET "/users/{id}"
GET http://localhost:8088/jpa/users/1 HTTP/1.1 200 Content-Type: application/json Transfer-Encoding: chunked Date: Wed, 25 Oct 2023 10:00:53 GMT Keep-Alive: timeout=60 Connection: keep-alive { "id": 1, "name": "zhyun1", "joinDate": "2023-10-25T19:00:48.985739", "password": "1111", "ssn": "701010-1111111", "_links": { "self": { "href": "http://localhost:8088/jpa/users/1", "type": "GET" }, "all-users": { "href": "http://localhost:8088/jpa/users", "type": "GET" } } } 응답 파일이 저장되었습니다. > 2023-10-25T190053.200.json Response code: 200; Time: 650ms (650 ms); Content length: 249 bytes (249 B)
HATEOAS 에 대해 배울 기회가 생겨서 공부하고는 있는데 controller가 너무 복잡해지는것 같다;
실무에서 잘 사용할까?
궁금한데 물어볼데가 읎그..,,,........,,.,,
로그를 찾아 헤매는 과정 기록
1. 분명 console 로그엔 id까지 잘 나타나는데
왤까
☹️
2. 브레이크 포인트 찍어서 디버깅 해보다가 발견
여기까진 값이 잘 들어있는것을 확인
여기까진 값이 잘 들어있는것을 확인 2
여기까진 값이 잘 들어있는것을 확인 3
오 도저히 못찾겠다 🤮
'에러기록' 카테고리의 다른 글