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로 올려봤는데 그대로였다
@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);
}
}
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)
@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);
}
}
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가 너무 복잡해지는것 같다;
실무에서 잘 사용할까?
궁금한데 물어볼데가 읎그..,,,........,,.,,
왤까 ☹️
여기까진 값이 잘 들어있는것을 확인
여기까진 값이 잘 들어있는것을 확인 2
여기까진 값이 잘 들어있는것을 확인 3
오 도저히 못찾겠다 🤮