인프런 커뮤니티 질문&답변

작성자 없음

작성자 정보가 삭제된 글입니다.

[개정판 2023-11-27] Spring Boot 3.x 를 이용한 RESTful Web Services 개발

Level3 단계의 REST API 구현을 위한 HATEOAS 적용

HATEOAS질문드립니다

작성

·

7.1K

1

UserControll쪽에 최신으로 올려주신 

package com.example.restfulwebservice.user;

import org.springframework.data.crossstore.ChangeSetPersister;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.validation.Valid;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;

@RestController
public class UserController {

private UserDaoService service;

//생성자를 통한 의존성 주입
public UserController(UserDaoService service) {
this.service = service;
}

@GetMapping("/users")
public List<User> retrieveAllUsers() {

return service.findAll();
}

// 전체 사용자 목록
@GetMapping("/users2")
public ResponseEntity<CollectionModel<EntityModel<User>>> retrieveUserList2() {
List<EntityModel<User>> result =
new ArrayList<>();
List<User> users = service.findAll();

for (User user : users) {
EntityModel entityModel = EntityModel.
of(user);
entityModel.add(linkTo(methodOn(this.getClass()).retrieveAllUsers()).withSelfRel());

result.add(entityModel);
}

return ResponseEntity.ok(CollectionModel.of(result, linkTo(methodOn(this.getClass()).retrieveAllUsers()).withSelfRel()));
}

//우리는 id를 숫자로 해도 서버측에 전달 될 경우에는 -> String으로 된다
//id로 하면 자동으로 원하는 int에 맞게 찾아준다
//HETAOS를 적용하면 개발자의 양은 많아지지만
//내가 개발한 것을 보는 사용자입장에서는 더 많은 정보를 알 수 있다
// 사용자 상세 정보
@GetMapping("/users/{id}")
public ResponseEntity<EntityModel<User>> retrieveUser(@PathVariable int id) {
User user =
service.findOne(id);

if (user == null) {
throw new UserNotFoundException("id-" + id);
}

EntityModel entityModel = EntityModel.
of(user);

WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retrieveAllUsers());
entityModel.add(linkTo.withRel("all-users"));
return ResponseEntity.ok(entityModel);

}

//post, put 처럼 데이터 맵핑 할려면 파라미터에 request body로 형식을 적어줘야한다
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User saveUser =
service.save(user);

URI localtion = ServletUriComponentsBuilder.fromCurrentRequest()
.path(
"/{id}")
.buildAndExpand(saveUser.getID())
.toUri()
;
return ResponseEntity.created(localtion).build();

}

@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable int id) {

User user =
service.deleteById( id);

if(user == null) {
throw new UserNotFoundException(String.format("ID[%s] not found ", id));
}
}
}
사용했는데 에러가 발생했습니다 ㅠㅠ
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.plugin.core.PluginRegistry<org.springframework.hateoas.client.LinkDiscoverer, org.springframework.http.MediaType>' available: expected single matching bean but found 3: relProviderPluginRegistry,linkDiscovererRegistry,entityLinksPluginRegistry

답변 1

4

Dowon Lee님의 프로필 이미지
Dowon Lee
지식공유자

안녕하세요, 이도원입니다. 

Spring Boot, HATEOAS의 버전이 최신 버전으로 변경되면서 몇몇 라이브러리에서 충돌이 발생한 것 같습니다. 

아래와 같이 pom.xml을 변경해서 빌드해 보시기 바랍니다. 

        <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
<!-- <version>2.1.8.RELEASE</version>-->
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
<version>3.3.6.RELEASE</version>
</dependency>

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>

pom.xml 파일의 변경으로 UserController.java의 Swagger 부분을 아래와 같이 변경하여 사용하시기 바랍니다.

//    @GetMapping("/users2")
// public Resources<Resource<User>> retrieveUserList() {
// List<Resource<User>> result = new ArrayList<>();
// List<User> users = service.findAll();
//
// for (User user : users) {
// Resource<User> resource = new Resource<>(user);
// ControllerLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retrieveAllUsers());
// resource.add(linkTo.withRel("all-users"));
//
// result.add(resource);
// }
//
// return new Resources(result);
// }

// 전체 사용자 목록
@GetMapping("/users2")
public ResponseEntity<CollectionModel<EntityModel<User>>> retrieveUserList2() {
List<EntityModel<User>> result = new ArrayList<>();
List<User> users = service.findAll();

for (User user : users) {
EntityModel entityModel = EntityModel.of(user);
entityModel.add(linkTo(methodOn(this.getClass()).retrieveAllUsers()).withSelfRel());

result.add(entityModel);
}

return ResponseEntity.ok(CollectionModel.of(result, linkTo(methodOn(this.getClass()).retrieveAllUsers()).withSelfRel()));
}
수정해 보시고 문의사항 있으시면 다시 글 남겨주세요. 

감사합니다.

해결했습니다 감사합니다.

작성자 없음

작성자 정보가 삭제된 글입니다.

질문하기