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

Spring2Boot님의 프로필 이미지
Spring2Boot

작성한 질문수

실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기 (Java 프로젝트 리팩토링)

17강. BookService.java를 Kotlin으로 변경하고 Optional 제거하기

allopen 플러그인 관련 질문입니다.

작성

·

938

1

안녕하세요. 강의 잘 듣고있습니다 :)

allopen 관련 질문이 하나 있는데요.

이전 강의에서 UserService를 코틀린으로 리팩토링했었는데 해당 과정부터 이번 BookService 리팩토링 강의까지 allopen 관련 에러가 발생하는 것 같습니다.

Failed to resolve parameter [com.group.libraryapp.domain.user.UserRepository userRepository] in constructor [public com.group.libraryapp.service.user.UserServiceTest(com.group.libraryapp.domain.user.UserRepository,com.group.libraryapp.service.user.UserService)]: Failed to load ApplicationContext
org.junit.jupiter.api.extension.ParameterResolutionException: Failed to resolve parameter [com.group.libraryapp.domain.user.UserRepository userRepository] in constructor [public com.group.libraryapp.service.user.UserServiceTest(com.group.libraryapp.domain.user.UserRepository,com.group.libraryapp.service.user.UserService)]: Failed to load ApplicationContext
	at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameter(ExecutableInvoker.java:239)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameters(ExecutableInvoker.java:183)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:74)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestClassConstructor(ClassBasedTestDescriptor.java:355)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateTestClass(ClassBasedTestDescriptor.java:302)
	at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:79)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:280)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:272)

리팩토링을 완료하고 테스트 코드를 실행시켜보면 위와 같은 에러가 발생합니다.

하지만 UserService의 클래스와 메소드들에 open을 붙여주면 정상적으로 돌아가더라구요.

plugins {
    id 'org.springframework.boot' version '2.6.8'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
    id 'org.jetbrains.kotlin.jvm' version '1.6.21'
    id 'org.jetbrains.kotlin.plugin.jpa' version '1.6.21'
    id "org.jetbrains.kotlin.plugin.allopen" version "1.6.21"
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

group = 'com.group'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
    implementation 'org.jetbrains.kotlin:kotlin-reflect:1.6.21'
    implementation 'org.junit.jupiter:junit-jupiter:5.7.0'
    implementation "org.assertj:assertj-core:3.11.1"
    implementation "org.springframework.boot:spring-boot-starter-test"

    runtimeOnly 'com.h2database:h2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation "org.assertj:assertj-core:3.11.1"
}

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

compileKotlin {
    kotlinOptions {
        jvmTarget = "11"
    }
}

compileTestKotlin {
    kotlinOptions {
        jvmTarget = "11"
    }
}

현재 제 build.gradle 파일도 같이 첨부합니다.

감사합니다 :)

답변 3

1

최태현님의 프로필 이미지
최태현
지식공유자

안녕하세요, 영식님!!!

build.gradle까지 첨부주시고~ 감사합니다 😊😊

아이고~ 맞습니다!!! 아마 16강에서 언급될텐데요! @Service 와 같은 스프링 빈을 코틀린에서 활용하기 위해서는 적어주신 플러그인이 필요합니다!!

 

플러그인을 적용했음에도 바이트코드로 확인하셨을 때 잘동작하지 않을 때는 1) gradle refresh를 해보시고, 2) IntelliJ를 종료했다가 재시작해보시면 될거에요!!

 

스프링 공식 문서로는 https://kotlinlang.org/docs/all-open-plugin.html 에서 참고하실 수 있습니다!!

 

추가로, 말씀해주신 allOpen 의 경우는 명시적으로 적용대상을 적어주어야 하는데, 현재는 javax.persistence.Entity 와 같이 JPA 관련 어노테이션이 붙은 경우에만 적용되서 @Service 클래스에는 적용되지 않은 것입니다.

 

감사합니다! 🙇🙇

1

Spring2Boot님의 프로필 이미지
Spring2Boot
질문자

자문자답합니다.

id "org.jetbrains.kotlin.plugin.spring" version "1.6.21"

build.gradlew에 위 라인 추가해주니까 정상 동작합니다!

1

Spring2Boot님의 프로필 이미지
Spring2Boot
질문자

추가적으로 바이트코드로 변환해봐도

 public final class com/group/libraryapp/service/book/BookService {


  @Lorg/springframework/stereotype/Service;()

  // access flags 0x11
  public final saveBook(Lcom/group/libraryapp/dto/book/request/BookRequest;)V

이런식으로 final이 붙어있는걸 보아 allopen이 제대로 적용되지 않는 것 같아요.

Spring2Boot님의 프로필 이미지
Spring2Boot

작성한 질문수

질문하기