Reputation: 11
I am developing a service by combining Kotlin, Spring Boot, multi-module, and hexagonal architecture.
While implementing the login logic, I encountered the following error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 1 of constructor in shop.hyeonme.global.jwt.JwtAdapter required a bean of type 'shop.hyeonme.domain.auth.spi.RefreshTokenPort' that could not be found.
Action:
Consider defining a bean of type 'shop.hyeonme.domain.auth.spi.RefreshTokenPort' in your configuration.
directory structure and files:
|- me
|- me-api
|- build.gradle.kts
|- src
|- main
|- kotlin
|- shop
|- hyeonme
|- MeServerApplication.kt
|- domain
|- auth
|- model
|- RefreshToken.kt
|- spi
|- JwtPort.kt
|- CommandRefreshTokenPort.kt
|- RefreshTokenPort.kt
|- global
|- jwt
|- JwtAdapter.kt
|- properties
|- JwtProperties.kt
|- config
|- ComponentScanConfig.kt
|- me-domain
|- build.gradle.kts
|- src
|- main
|- kotlin
|- shop
|- hyeonme
|- domain
|- auth
|- entity
|- RefreshTokenEntity.kt
|- repository
|- RefreshTokenRepository.kt
|- RefreshTokenPersistenceAdapter.kt
package shop.hyeonme.domain.auth.spi
import shop.hyeonme.domain.auth.model.RefreshToken
interface CommandRefreshTokenPort {
fun saveRefreshToken(refreshToken: RefreshToken): RefreshToken
}
package shop.hyeonme.domain.auth.spi
interface RefreshTokenPort : CommandRefreshTokenPort
package shop.hyeonme.domain.auth
import org.springframework.stereotype.Component
import shop.hyeonme.domain.auth.mapper.toEntity
import shop.hyeonme.domain.auth.mapper.toModel
import shop.hyeonme.domain.auth.model.RefreshToken
import shop.hyeonme.domain.auth.repository.RefreshTokenRepository
import shop.hyeonme.domain.auth.spi.RefreshTokenPort
@Component
class RefreshTokenPersistenceAdapter(
private val refreshTokenRepository: RefreshTokenRepository
) : RefreshTokenPort {
override fun saveRefreshToken(refreshToken: RefreshToken): RefreshToken =
refreshTokenRepository.save(refreshToken.toEntity()).toModel()
}
package shop.hyeonme.global.config
import org.springframework.context.annotation.ComponentScan.Filter
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.FilterType
import shop.hyeonme.common.annotation.*
@Configuration
@ComponentScan(
basePackages = ["shop.hyeonme"],
includeFilters = [
Filter(
type = FilterType.ANNOTATION,
classes = [
UseCase::class,
ReadOnlyUseCase::class,
Service::class,
QueryService::class,
CommandService::class
]
)
]
)
class ComponentScanConfig
me- api build.gradle.kts
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
kapt("org.springframework.boot:spring-boot-configuration-processor")
runtimeOnly ("com.mysql:mysql-connector-j")
implementation("io.jsonwebtoken:jjwt-api:0.11.2")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.2")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.2")
implementation(kotlin("stdlib-jdk8"))
}
kapt {
arguments {
arg("mapstruct.defaultComponentModel", "spring")
arg("mapstruct.unmappedTargetPolicy", "ignore")
}
}
me-domain build.gradle.kts
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
kotlin("plugin.jpa") version "1.8.10"
kotlin("plugin.spring") version "1.8.10"
}
val jar: Jar by tasks
val bootJar: BootJar by tasks
jar.enabled = true
bootJar.enabled = false
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-data-redis:2.7.5")
runtimeOnly ("com.mysql:mysql-connector-j")
implementation("com.querydsl:querydsl-jpa:5.0.0")
kapt("com.querydsl:querydsl-apt:5.0.0:jpa")
implementation(project(":me-api"))
}
allOpen {
annotation("javax.persistence.Entity")
annotation("javax.persistence.MappedSuperclass")
annotation("javax.persistence.Embeddable")
}
noArg {
annotation("javax.persistence.Entity")
annotation("javax.persistence.MappedSuperclass")
annotation("javax.persistence.Embeddable")
}
I made numerous attempts, such as changing the directory structure and renaming files, but 'me-api' couldn't retrieve the bean from 'me-domain'.
Upvotes: 1
Views: 88