I am trying to introduce to Spring JPA and I have difficulties running up my tests.
My gradle.build.kts looks like the following
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.4.0"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
kotlin("jvm") version "1.4.10"
kotlin("plugin.spring") version "1.4.10"
kotlin("plugin.jpa") version "1.4.10"
}
group = "com.pluralsight"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
jcenter()
google()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
runtimeOnly("com.h2database:h2")
testImplementation(platform("org.junit:junit-bom:5.7.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
I am using Junit5 for my test framework. And what first I need to test is that my Flight Entity is created correctly. I am not using #SpringRunner since we are on Junit5 so I do the following:
package com.pluralsight.springdataoverview
import com.pluralsight.springdataoverview.entity.Flight
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.boot.test.context.SpringBootTest
import java.time.LocalDateTime
import javax.persistence.EntityManager
#SpringBootTest
#DataJpaTest
class SpringDataOverviewApplicationTests {
#Autowired
private val entityManager: EntityManager? = null
#Test
fun verifyFlighTCanBeSaved() {
var flight = Flight()
flight.origin = "London"
flight.destination = "New York"
flight.scheduledAt = LocalDateTime.parse("2011-12-13T12:12:00")
entityManager!!.persist(flight)
val flights = entityManager
.createQuery("SELECT f FROM Flight f", Flight::class.java)
.resultList
Assertions.assertEquals(flights.first(), flight)
}
}
And I have the following in red
What dependency I am missing ?
You have multiple declarations of configuration (that's what your error message is saying).
It's because you are using #SpringBootTest and #DataJpaTest in the same configuration class i.e SpringDataOverviewApplicationTests.
Use either of it and it should be fine.
Related
I'm currently getting the following error when I try to test my service:
Execution failed for task ':compileTestKotlin'.
> Error while evaluating property 'filteredArgumentsMap' of task ':compileTestKotlin'.
> Could not resolve all files for configuration ':testCompileClasspath'.
> Could not find org.springframework.boot:spring-boot-security-test:.
Required by:
project :
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
Currently, my test file looks like this:
class UserServiceTest {
val userRepository: HireOutUserRepository = mockk()
val passwordEncoder: BCryptPasswordEncoder = BCryptPasswordEncoder()
val userService: UserService = UserServiceImpl(userRepository, passwordEncoder)
#Test
fun whenGetAllUsers_thenReturnSize() {
verify(exactly = 0) { userService.getUsers() }
}
}
and my build.gradle.kts looks like this:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.0.1"
id("io.spring.dependency-management") version "1.1.0"
kotlin("jvm") version "1.7.22"
kotlin("plugin.spring") version "1.7.22"
}
group = "com.jre"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
//implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
runtimeOnly("com.h2database:h2")
//testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.boot:spring-boot-security-test")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
exclude(group = "org.mockito", module = "mockito-core")
}
testImplementation("org.junit.jupiter:junit-jupiter-engine")
testImplementation("io.mockk:mockk:1.13.2")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
I'm not sure what is going on to cause the error to trigger as this should be a simple test scenario in my code.
Thanks
Dependency is incorrect. The correct dependency is this.
testImplementation 'org.springframework.security:spring-security-test'
Please add this in build.gradle file and try again
When creating a minimal Kotlin Spring Boot 3 application, I am get a runtime error when executing the native (GraalVM) image. The error message is:
Failed to create query for method public abstract java.lang.Object org.springframework.data.repository.kotlin.CoroutineCrudRepository.count(kotlin.coroutines.Continuation); No property 'count' found for type 'Customer'
where 'Customer' is a data class entity.
I created a simple gradle based application with SpringBoot v3-RC1 consisting of one class
package org.test.nativedemo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.data.annotation.Id
import org.springframework.data.repository.kotlin.CoroutineCrudRepository
#SpringBootApplication
class NativeDemoApplication
fun main(args: Array<String>) {
runApplication<NativeDemoApplication>(*args)
}
interface CustomerRepository : CoroutineCrudRepository<Customer, Int>
data class Customer(#Id val id: Int?, val name: String)
when running (through Gradle) with the following build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.0.0-RC1"
id("io.spring.dependency-management") version "1.1.0"
id("org.graalvm.buildtools.native") version "0.9.16"
kotlin("jvm") version "1.7.20"
kotlin("plugin.spring") version "1.7.20"
kotlin("plugin.serialization") version "1.7.20"
}
group = "org.test"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
maven { url = uri("https://repo.spring.io/milestone") }
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
runtimeOnly("org.postgresql:postgresql")
runtimeOnly("org.postgresql:r2dbc-postgresql")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
It compiles and builds native image. There is a runtime error stating
Failed to create query for method public abstract java.lang.Object org.springframework.data.repository.kotlin.CoroutineCrudRepository.count(kotlin.coroutines.Continuation); No property 'count' found for type 'Customer'
I am trying to create a project with current Kotlin, MapStruct and Java using Spring-Boot folowing some online examples, as I am new to MapStruct, however I am not able to inject the mapper into my service. Both Idea and Gradle (in build task test) complain that no bean has been found (UnsatisfiedDependencyException). Googling didn't help. What am I missing?
MWE:
build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.7.4"
id("io.spring.dependency-management") version "1.0.14.RELEASE"
kotlin("jvm") version "1.7.20"
kotlin("plugin.spring") version "1.7.20"
kotlin("plugin.jpa") version "1.7.20"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
testImplementation("org.springframework.boot:spring-boot-starter-test")
implementation("org.mapstruct:mapstruct:1.5.3.Final")
annotationProcessor("org.mapstruct:mapstruct-processor:1.5.3.Final")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
DemoAppllication.kt
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
#SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
App.kt
package com.example.demo
import org.mapstruct.Mapper
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service
import javax.persistence.*
#Entity
#Table(name = "items")
class Item(#Id var id: Int = 0)
data class ItemDto(val id: Int)
#Repository
interface ItemRepo : JpaRepository<Item, Int>
#Mapper(componentModel = "spring")
interface ItemMapper {
fun entToDto(item: Item) : ItemDto
fun entsToDtos(items: List<Item>) : List<ItemDto>
fun dtoToEnt(itemDto: ItemDto) : Item
}
#Service
class Srvc(private val itemMapper: ItemMapper, // XXX: no bean found for this one
private val repo: ItemRepo)
{
fun items() = itemMapper.entsToDtos(repo.findAll())
}
// controller skipped
Kapt is in maintenance mode! See example: https://github.com/mapstruct/mapstruct-examples/tree/main/mapstruct-kotlin
plugin {
// ...
kotlin("kapt")
// ...
}
dependencies {
// ...
kapt("org.mapstruct:mapstruct-processor:$version")
implementation("org.mapstruct:mapstruct:$version")
// ...
}
EDIT (by mpts.cz — for future me or anyone as new to Mapstruct and/or Gradle as I am):
use plugin kotlin("kapt")
replace annotationProcessor("org.mapstruct:mapstruct-processor:$version")
with kapt("org.mapstruct:mapstruct-processor:$version")
put the previous line before implementation("org.mapstruct:mapstruct:$version")
With these changes all seems to work smoothly. Thanks Numichi!
With org.springframework.boot version 2.5.9, thinks work fine, but with 2.6.0 (2.6.1, 2.6.2, 2.6.3), I get the following error:
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'sentryOptions': Requested bean is currently in creation: Is there an unresolvable circular reference?
(full log: https://gist.github.com/Dobiasd/be7810282a06b538ccee0078ab2267aa)
Here is my minimal example to reproduce the issue:
Application.kt:
package com.acme.foo.bar
import io.sentry.spring.EnableSentry
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Configuration
#EnableSentry
#Configuration
class SentryConfiguration
#SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
IntegrationTest.kt:
package com.acme.foo.bar.integration
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.junit.jupiter.SpringExtension
#ExtendWith(SpringExtension::class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class FullStackTest {
#Test
fun init_context() {
}
}
build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.6.3"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.6.10"
kotlin("plugin.spring") version "1.6.10"
}
group = "com.acme"
version = "1.0.0-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
implementation(group = "org.springframework.boot", name = "spring-boot-starter-web")
implementation(group = "io.sentry", name = "sentry-spring", version = "5.5.3")
testImplementation(group = "org.springframework.boot", name = "spring-boot-starter-test")
testImplementation(group = "org.jetbrains.kotlin", name = "kotlin-test-junit")
}
tasks {
withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
withType<Test> {
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
useJUnitPlatform()
}
}
Any ideas what I'm doing wrong? Or maybe sentry-spring just does work with Spring Boot 2.6.x (yet)?
Found the solution. Instead of io.sentry:sentry-spring one has to use io.sentry:sentry-spring-boot-starter in the dependencies and then remove the following from the code:
#EnableSentry
#Configuration
class SentryConfiguration
I've just tested in my actual project, and logged errors are still sent to Sentry correctly.
I am trying to follow https://github.com/spring-projects/spring-kafka/issues/361 to pass topic names from .yml file to the #kafkalistener. But the compiler throws following error
Type mismatch.
Required:
Array<String>
Found:
String
Unresolved reference: spring
Below is the receiver code
#Component
class Receiver {
companion object {
private val LOGGER = LoggerFactory.getLogger(Receiver::class.java)
}
#Autowired
private val taskExecutor: TaskExecutor? = null
#Autowired
private val applicationContext: ApplicationContext? = null
#KafkaListener(topics = "#{'${spring.kafka.topics}'.split(',')}")
fun receive(#Header(KafkaHeaders.RECEIVED_TOPIC) topic: String) {
}
}
Below is my build.gradle file
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.1.7.RELEASE"
id("io.spring.dependency-management") version "1.0.8.RELEASE"
kotlin("jvm") version "1.2.71"
kotlin("plugin.spring") version "1.2.71"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.springframework.kafka:spring-kafka")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
What am i missing here?
This works for me:
#KafkaListener(topics = ["#{'\${test.topics}'.split(',')}"])
Pay attention how I had to apply Kotlin syntax to the annotation attribute value.
Also Keep in mind that $ is a template specific operator in Kotlin, so we need to escape it to make it as a plain symbol for further properties placeholder resolution.