인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

1026baby님의 프로필 이미지
1026baby

작성한 질문수

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

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

Cannot resolve symbol 'EntityModel' (+ RepresentationModel)

작성

·

589

0

두 가지 질문이 있습니다.

  1. EntityModel을 찾을 수 없다고 나오는데 도움을 받을 수 있을까요??

  2. 공식문서에는 RepresentationModel를 상속하여 기능을 추가하라고 가이드하고 있는데, EntityModel와 다른가요?

1. cannot resolve symbol 'EntityModel'

제 코드와 설정은 아래와 같습니다.

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.0'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    // web 라이브러리
    implementation 'org.springframework.boot:spring-boot-starter-web'
    // JPA
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    // JDBC
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    // 타임리프
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
    // TEST
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    // VALIDATION
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    // 롬복
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
}

tasks.named('test') {
    useJUnitPlatform()
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>dateanu</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dateanu</name>
    <description>dateanu</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.4</version>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

# DATABASE
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# spring.datasource.url=jdbc:h2:~/local
spring.datasource.url=jdbc:h2:~/local;AUTO_SERVER=true
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

# PORT
server.port=9090

# JPA
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
# USE THIS
spring.jpa.hibernate.ddl-auto=create
# spring.jpa.hibernate.ddl-auto=update // OR THIS
# AVOID THIS
# spring.jpa.hibernate.ddl-auto=create
# spring.jpa.hibernate.ddl-auto=create-drop

spring.messages.basename=messages
spring.messages.fallback-to-system-locale=false

Controller

package com.example.dateanu.rest_api;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.net.URI;
import java.util.List;

@RestController
@RequiredArgsConstructor
public class UserController {
    private final UserDaoService service; // 싱글톤 객체를 생성자주입을 하기 위해 꼭 final이 붙어야한다.

    @GetMapping("/users")
    public List<User> retrieveAllUsers() {
        return service.findAll();
    }

    // GET /users/1
    @GetMapping("/users/{id}")
    public User retrieveUser(@PathVariable int id) {
        User user =  service.findOne(id);

        if(user == null){
            throw new UserNotFoundException(String.format("ID[%s] not found",id));
        }

        // HATEOAS


        return user;
    }

    @PostMapping("/users")
    public ResponseEntity<User> createUser(@Valid @RequestBody User user){
        User savedUser = service.save(user);

        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(savedUser.getId())
                .toUri();

        return ResponseEntity.created(location).build();
    }


    @DeleteMapping("/users/{id}")
    public ResponseEntity<User> deleteUser(@PathVariable int id){
        User user = service.deleteById(id);

        if(user == null){
            throw new UserNotFoundException(String.format("ID[%s] not found"));
        }

        return new ResponseEntity<>(user, HttpStatus.OK);
    }

    @PutMapping("/users/{id}")
    public ResponseEntity<User> replaceUser(@PathVariable int id,@RequestBody User user){
        User replacedUser = service.replace(id,user);

        return new ResponseEntity<>(replacedUser, HttpStatus.OK);
    }

    @PatchMapping("/users/{id}")
    public ResponseEntity<User> updateUser(@PathVariable int id,@RequestBody User user){
        User updatedUser = service.update(id,user);

        return new ResponseEntity<>(updatedUser, HttpStatus.OK);
    }
}

어떤 것 때문인지 몇 시간을 구글링하고 디버깅해봐도 해결되지가 않네요 ㅠㅠ

** 2.4.4 version에 hateoas 의존성 추가했으며, Gradle, Maven 모두 refresh 하였습니다.

2.

공식문서에서는 RepresentationModel 을 상속받아 쓰게끔 가이드가 되어있는 것을 확인했습니다.

https://spring.io/guides/gs/rest-hateoas/

EntityModel을 사용하는 것과 다른 것인지, 어떤 것이 best practice 인지 알려주실 수 있나요??

** 이 또한 cannot resolve symbol 'representationmodel' 에러가 발생하네요 ㅠㅠ

 

감사합니다 :-)

답변 3

1

안녕하세요, 인프런 AI 인턴이에요.

코드를 확인해보니 build.gradle에는 Spring Boot 3.0.0 버전을 사용하고 계시는데요, EntityModel은 Spring HATEOAS 라이브러리에 속한 클래스입니다. Spring HATEOAS 1.x 버전에서는 RepresentationModel을 사용하고, 1.x 이전 버전에서는 EntityModel을 사용합니다.

따라서, EntityModel 클래스를 사용하시려면 build.gradle 파일에 Spring HATEOAS 의존성을 추가해주셔야 합니다.

build.gradle 파일의 dependencies 블록에 다음과 같이 추가해보세요.

implementation ‘org.springframework.boot:spring-boot-starter-hateoas’

그리고 프로젝트를 다시 빌드해보세요. EntityModel 클래스를 사용할 수 있을 것입니다.

이렇게 하면 EntityModel을 사용할 수 있을 것입니다. 혹시 문제가 계속되면 프로젝트 파일의 캐시를 삭제하고 IDE를 재시작해보세요. 문제가 해결되지 않을 경우, 프로젝트에서 사용 중인 다른 라이브러리와의 충돌로 인한 문제일 수도 있으니 확인해보시는 것도 좋을 것 같아요.

더 질문이 있으시면 언제든지 물어보세요. 좋은 하루 되세요!

0

1026baby님의 프로필 이미지
1026baby
질문자

https://docs.spring.io/spring-hateoas/docs/current/reference/html/

위 레퍼런스를 찾아보니 HATEOAS에 대한 모델을 정의하고자할 때는 HATEOAS의 최상위 클래스인 RepresentationModel 을 상속받기를 권장하며, EntityModel은 단순한 하나의 객체로 반환할 때 사용하라고 나와있습니다.
아래 블로그도 찾아보시면 좋을 것 같네요

https://halfstorage.tistory.com/60

0

1026baby님의 프로필 이미지
1026baby
질문자

@인프런 AI 인턴
감사합니다. build.gradle들을 확인해보니 제대로 할 수 있었습니다.

다만 최근 EntityModel에 대한 표준이 바뀐 것 같아

아래 강사님의 답변을 참고하시면 좋을 것 같습니다.


https://www.inflearn.com/questions/203512/entitymodel-deprecated-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%B0%94%EA%BE%B8%EB%A9%B4-%EB%90%A0%EA%B9%8C%EC%9A%94

1026baby님의 프로필 이미지
1026baby

작성한 질문수

질문하기