net.bytebuddy.byte-buddy-gradle-plugin should support kotlin project as well
Closed this issue · 8 comments
Just want using gradle kotlin to run the example but not working
error logs
2022-07-16 23:05:52.505 INFO 10203 --- [ main] com.snacks.ApplicationKt : Started ApplicationKt in 2.37 seconds (JVM running for 2.533)
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.snacks.OrderRepository' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
at com.snacks.ApplicationKt.main(Application.kt:17)
and the issue seems relate to - Processing class files located in in: /snacks/build/classes/java/raw
which not using kotlin package, and related bytebuddy codes below
ByteBuddyTaskConfiguration
@Override
protected void configureDirectories(SourceDirectorySet source, JavaCompile compileTask, ByteBuddyTask byteBuddyTask) {
try {
DirectoryProperty directory = (DirectoryProperty) getDestinationDirectory.invoke(source);
setDestinationDir.invoke(compileTask, directory.dir(RAW_FOLDER).map(ToFileMapper.INSTANCE));
byteBuddyTask.getSource().set(directory.dir(RAW_FOLDER));
byteBuddyTask.getTarget().set(directory);
byteBuddyTask.getClassPath().from(compileTask.getClasspath());
} catch (Exception exception) {
throw new GradleException("Could not adjust directories for tasks", exception);
}
}
2022-07-18T13:01:24.857+0800 [INFO] [org.gradle.internal.execution.steps.ResolveCachingStateStep] Caching disabled for task ':byteBuddy' because:
Build cache is disabled
2022-07-18T13:01:24.860+0800 [DEBUG] [org.gradle.internal.execution.steps.SkipUpToDateStep] Determining if task ':byteBuddy' is up-to-date
2022-07-18T13:01:24.860+0800 [INFO] [org.gradle.internal.execution.steps.SkipUpToDateStep] Task ':byteBuddy' is not up-to-date because:
Output property 'target' file /snacks/build/classes/java/main has been removed.
2022-07-18T13:01:24.861+0800 [DEBUG] [org.gradle.internal.vfs.impl.AbstractVirtualFileSystem] Invalidating VFS paths: [/snacks/build/classes/java/main]
2022-07-18T13:01:24.862+0800 [DEBUG] [org.gradle.internal.execution.steps.CreateOutputsStep] Ensuring directory exists for property target at /snacks/build/classes/java/main
2022-07-18T13:01:24.863+0800 [INFO] [org.gradle.internal.execution.steps.ResolveInputChangesStep] The input changes require a full rebuild for incremental task ':byteBuddy'.
2022-07-18T13:01:24.863+0800 [DEBUG] [org.gradle.internal.file.impl.DefaultDeleter] Deleting /snacks/build/classes/java/main
2022-07-18T13:01:24.863+0800 [DEBUG] [org.gradle.api.internal.tasks.execution.TaskExecution] Executing actions for task ':byteBuddy'.
2022-07-18T13:01:24.868+0800 [DEBUG] [org.gradle.api.Task] Applying non-incremental build
2022-07-18T13:01:24.876+0800 [DEBUG] [org.gradle.api.Task] 1 plugins are being applied via configuration and discovery
2022-07-18T13:01:24.876+0800 [INFO] [org.gradle.api.Task] Resolved plugin: org.jmolecules.bytebuddy.JMoleculesPlugin
2022-07-18T13:01:24.975+0800 [INFO] [org.gradle.api.Task] Processing class files located in in: /snacks/build/classes/java/raw
2022-07-18T13:01:24.976+0800 [DEBUG] [org.gradle.api.Task] Java version was configured: 18
2022-07-18T13:01:24.984+0800 [WARN] [org.gradle.api.Task] No types were transformed during plugin execution
2022-07-18T13:01:24.984+0800 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Execute apply for :byteBuddy' completed
build.gradle.kts configs below
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript {
dependencies {
classpath(platform("org.jmolecules:jmolecules-bom:2022.2.0"))
classpath("org.jmolecules.integrations:jmolecules-bytebuddy")
classpath("org.jmolecules.integrations:jmolecules-spring")
classpath("org.jmolecules.integrations:jmolecules-jpa")
}
}
plugins {
id("org.springframework.boot") version "2.7.0"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.6.21"
id("org.jetbrains.kotlinx.kover") version "0.5.1"
kotlin("plugin.spring") version "1.6.21"
kotlin("plugin.jpa") version "1.6.21"
id("net.bytebuddy.byte-buddy-gradle-plugin") version "1.12.12"
idea
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
dependencies {
implementation(platform("org.jmolecules:jmolecules-bom:2022.2.0"))
implementation("net.bytebuddy:byte-buddy-gradle-plugin:1.12.10")
implementation("org.jmolecules.integrations:jmolecules-bytebuddy")
implementation("org.jmolecules.integrations:jmolecules-spring")
implementation("org.jmolecules.integrations:jmolecules-jpa")
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.springframework.session:spring-session-jdbc")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jmolecules:kmolecules-ddd")
implementation("org.springdoc:springdoc-openapi-ui:1.6.9")
implementation("org.springdoc:springdoc-openapi-kotlin:1.6.9")
implementation("com.vladmihalcea:hibernate-types-55:2.16.2")
implementation("org.projectlombok:lombok")
runtimeOnly("mysql:mysql-connector-java:8.0.29")
implementation("com.h2database:h2:2.1.212")
testImplementation("org.mockito.kotlin:mockito-kotlin:4.0.0")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks {
byteBuddy {
transformation {
plugin = org.jmolecules.bytebuddy.JMoleculesPlugin::class.java
}
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
test {
extensions.configure(kotlinx.kover.api.KoverTaskExtension::class) {
isEnabled = true
binaryReportFile.set(file("$buildDir/kover/test.exec"))
}
useJUnitPlatform()
// testLogging {
// events("passed", "skipped", "failed")
// }
finalizedBy(koverHtmlReport)
}
koverHtmlReport {
isEnabled = true
htmlReportDir.set(layout.buildDirectory.dir("reports/kover/html"))
}
}
kotlin application
@SpringBootApplication
open class Application
fun main(args: Array<String>) {
val context = runApplication<Application>(*args)
val repository = context.getBean(OrderRepository::class.java)
val order = repository.save(Order())
}
@Table(name = "KotlinOrder")
open class Order : AggregateRoot<Order, Order.OrderIdentifier> {
override val id = OrderIdentifier(UUID.randomUUID())
data class OrderIdentifier(val id: UUID) : Identifier
}
interface OrderRepository : CrudRepository<Order, Order.OrderIdentifier>
At this point, the Gradle plugin does unfortunately not support Kotlin. Gradle requires a lot of work to inject a task in the workflow, so only Java classes are automatically intercepted. But you can configure your own ByteBuddyTask
when using the plugin. You would need to point it to the Kotlin output folder to instrument the classes.
I was however under the impression that Kotlin adds its source sets to the Java source sets. Maybe that's another way of doing it.
At this point, the Gradle plugin does unfortunately not support Kotlin. Gradle requires a lot of work to inject a task in the workflow, so only Java classes are automatically intercepted. But you can configure your own
ByteBuddyTask
when using the plugin. You would need to point it to the Kotlin output folder to instrument the classes.I was however under the impression that Kotlin adds its source sets to the Java source sets. Maybe that's another way of doing it.
Yep, ByteBuddyTask works for kotlin by specific output folder
At this point, the Gradle plugin does unfortunately not support Kotlin. Gradle requires a lot of work to inject a task in the workflow, so only Java classes are automatically intercepted. But you can configure your own
ByteBuddyTask
when using the plugin. You would need to point it to the Kotlin output folder to instrument the classes.I was however under the impression that Kotlin adds its source sets to the Java source sets. Maybe that's another way of doing it.
And how do I point the ByteBuddyTask to the Kotlin output folder? I messed arround with gradle sourceSets but I can't get it working. I would appreciate if you have a code example for me.
You would need to get hold of the task and change its target source property: https://github.com/raphw/byte-buddy/blob/master/byte-buddy-gradle-plugin/src/main/java/net/bytebuddy/build/gradle/ByteBuddyTask.java#L66
It's probably possible by reading the task and to call that setter. Easier, you would probably just create new task and set it up in its entirety.
Easier, you would probably just create new task and set it up in its entirety.
What do you mean by that? Should I create a Gradle Task an call the ByteBuddy Java API directly instead of using the ByteBuddy Gradle Plugin? Or is there a way to set up the source directory of the ByteBuddy Plugin in a new task? Unfortunately I have not much experience with Gradle Plugins. It would be great if you could provide me an example code of how to setup the source of the ByteBuddy Plugin.
Unfortunately, I have little experience with Gradle and Kotlin. But you could create your own ByteBuddyTask and hook it into the task chain.
Do you mean that I should create a Gradle Task like that:
task("custom bytebuddy") {
sourceSets.getByName("main").java.srcDirs("build/kotlin")
byteBuddy {
transformation {
// Needs to be declared explicitly
plugin = org.jmolecules.bytebuddy.JMoleculesPlugin::class.java
}
}
}
Or should I extend the ByteBuddy Java class and then wire this Custom class up in Gradle?
A Groovy / Java example would be perfectly fine to me.
I think you have to specify the task type: ByteBuddyTask
and then invoke the appropriate setters. But I would consult a Gradle forum for that, I am not a specialist on Gradle.