-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dev mode is not working in a gradle multimodule setup when kotlin code is used #35577
Comments
/cc @evanchooly (kotlin), @geoand (kotlin), @glefloch, @maxandersen (jbang), @quarkusio/devtools (jbang) |
Some more inputs to narrow the problem down: if we look at the
We see that there are 2 folders:
I have the feeling that Quarkus is only looking at I didn't look yet at how this is implemented, but when you ask Gradle (inside a gradle task/plugin) about the output of the main sourceSet: JavaPluginExtension extension = project.getExtensions().findByType(JavaPluginExtension.class);
SourceSet mainSourceSet = extension.getSourceSets().getByName("main");
for (File f : mainSourceSet.getOutput().getFiles()) {
System.out.println(f);
} you see the different folders at output of the main source-set:
See jmini/quarkus_issue35577@d9f765e that adds a An other experiment to work-around this issue: When I add a task that copy the content of Then it seems that quarkus dev-mode is working correctly:
I also had to:
And of course for gradle this strategy is really wrong, since it break all the input/output concept. And the compile task will not be UP_TO_DATE since my copy task is changing the output of the compile-java task. |
@jmini maybe you can have a look at what the Gradle plugin is doing and provide a fix? That would be helpful. |
I did not dig into that part of the code yet. :-) A very naive search pointed to this test: Lines 89 to 104 in a2517e8
Which make me think my use case should be supported... But probably this is a complete different step and not related to my issue. Do you have some implementation details/documentation about how the gradle plugin is working (which steps create which output and what is the difference between devMode and production build)? I would like to narrow down the part that is not working. Maybe the issue is in the GradleApplicationModelBuilder, but I am not sure how to continue my investigations. Should I verify if the application model is as expected? Or different between production mode and dev mode? Should I verify if the classpath of the started application is correct? (for instance that both The classpath seems only to be Can the application model |
I started a jbang script to do this: QuarkusAppMain.java It could probably be improved to display the values in a nice way, but I think this is enough to already see that gradle did not create the app model correctly. When I deserialized the
I think the |
@jmini yes you are right, the path |
The workaround I proposed couple of days ago is not really working in all cases. I did not find the correct moment where
This works in the reproducer project: But in our real application I am still having hard time to find why it doesn't work. The |
I did some debugging into the issue. Breakpoint is at Lines 523 to 532 in 99ee1af
When we are building the model for Stack at breakpoint
From a gradle task point of view we are at starting the
First finding: The way Otherwise the method is skipped because of the try-catch: Lines 529 to 531 in 99ee1af
Print of the Stacktrace of the exception in the catch:``` java.lang.ClassNotFoundException: org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445) at org.gradle.internal.classloader.VisitableURLClassLoader$InstrumentingVisitableURLClassLoader.findClass(VisitableURLClassLoader.java:186) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:375) at io.quarkus.gradle.tooling.GradleApplicationModelBuilder.maybeConfigureKotlinJvmCompile(GradleApplicationModelBuilder.java:527) at io.quarkus.gradle.tooling.GradleApplicationModelBuilder.initProjectModule(GradleApplicationModelBuilder.java:487) at io.quarkus.gradle.tooling.GradleApplicationModelBuilder.initProjectModuleAndBuildPaths(GradleApplicationModelBuilder.java:403) at io.quarkus.gradle.tooling.GradleApplicationModelBuilder.collectDependencies(GradleApplicationModelBuilder.java:337) at io.quarkus.gradle.tooling.GradleApplicationModelBuilder.lambda$collectDependencies$4(GradleApplicationModelBuilder.java:243) at java.base/java.lang.Iterable.forEach(Iterable.java:75) at io.quarkus.gradle.tooling.GradleApplicationModelBuilder.collectDependencies(GradleApplicationModelBuilder.java:242) at io.quarkus.gradle.tooling.GradleApplicationModelBuilder.buildAll(GradleApplicationModelBuilder.java:123) at io.quarkus.gradle.tooling.ToolingUtils.create(ToolingUtils.java:74) at io.quarkus.gradle.tooling.ToolingUtils.create(ToolingUtils.java:70) at io.quarkus.gradle.extension.QuarkusPluginExtension.getApplicationModel(QuarkusPluginExtension.java:181) at io.quarkus.gradle.tasks.QuarkusDev.newLauncher(QuarkusDev.java:447) at io.quarkus.gradle.tasks.QuarkusDev.startDev(QuarkusDev.java:342) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:125) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29) at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:242) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47) at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68) at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:227) at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:210) at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:193) at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:166) at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:105) at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:44) at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:59) at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:56) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53) at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73) at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:56) at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:44) at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:67) at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:37) at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:41) at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:74) at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55) at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:50) at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:28) at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.executeDelegateBroadcastingChanges(CaptureStateAfterExecutionStep.java:100) at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:72) at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:50) at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:40) at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:29) at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:166) at org.gradle.internal.execution.steps.BuildCacheStep.lambda$execute$1(BuildCacheStep.java:70) at org.gradle.internal.Either$Right.fold(Either.java:175) at org.gradle.internal.execution.caching.CachingState.fold(CachingState.java:59) at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:68) at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:46) at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:36) at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:25) at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:36) at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:22) at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:91) at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$2(SkipUpToDateStep.java:55) at java.base/java.util.Optional.orElseGet(Optional.java:364) at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55) at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:37) at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:65) at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:36) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27) at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:76) at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:37) at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:94) at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:49) at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:71) at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:45) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.executeWithNonEmptySources(SkipEmptyWorkStep.java:177) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:81) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:53) at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:32) at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:21) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38) at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36) at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23) at org.gradle.internal.execution.steps.CleanupStaleOutputsStep.execute(CleanupStaleOutputsStep.java:75) at org.gradle.internal.execution.steps.CleanupStaleOutputsStep.execute(CleanupStaleOutputsStep.java:41) at org.gradle.internal.execution.steps.AssignWorkspaceStep.lambda$execute$0(AssignWorkspaceStep.java:32) at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:287) at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:30) at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:21) at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:37) at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:27) at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:47) at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:34) at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:64) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:146) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:135) at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74) at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53) at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:337) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:324) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:317) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:49) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:833) ``` In the reproducer only Second finding: Even after adding the kotlin plugin in The reason is that when you ask for tasks Verifier checkout the branch
This task is defined in the --> and:
This task is defined in the --> @aloubyansky it is a place you seems to know (from issue #20755) |
At the end I am not sure why the
Because the cardinality does not match, with the Gradle sourceSet model. If you take a pure java project with 2 java source folders:
with this
The
If we consider the
Created by multiple source folders and multiple tasks (which is the information available in the ConfigurableFileCollection without too much hacks as it is now) My current work-around is to take the See my proposal: jmini@a426765 and let me know if I should file that as a PR. |
As discussed on Zulip: I am wondering if the quarkus application model ( The quarkus model:
The Gradle SourceSet model:
Example with a simple project with the kotlin extension (link to generate on code.quarkus.io). If I inspect the main SourceSet I have:
And the are more complicated stuff that can be done in gradle (like more compile plugins or having a task that generate resources directly and register it to the main source set output with a My feeling is that because the Quarkus model is built like this, it is really difficult to map the Gradle model into the Quarkus one. And this makes the implementation of Lines 472 to 521 in 99ee1af
The complexity of this method (checking each task by type Some notes on the Gradle API: Simple printInfo task to inspect the main source-set
tasks.register('printInfo') {
doLast {
def mainSourceSet = sourceSets.main
println(mainSourceSet)
println("all sources srcDirs: ")
mainSourceSet.getAllSource().getSrcDirs().each {
println("- " + it.getAbsolutePath().substring(project.getRootProject().getProjectDir().getAbsolutePath().length() + 1))
}
println("resources srcDirs: ")
mainSourceSet.getResources().getSrcDirs().each {
println("- " + it.getAbsolutePath().substring(project.getRootProject().getProjectDir().getAbsolutePath().length() + 1))
}
println("ouput ClassesDir: ")
mainSourceSet.getOutput().getClassesDirs().each {
println("- " + it.getAbsolutePath().substring(project.getRootProject().getProjectDir().getAbsolutePath().length() + 1))
}
println("ouput ClassesDir builtBy: ")
(mainSourceSet.getOutput().getClassesDirs() as org.gradle.api.file.ConfigurableFileCollection).getBuiltBy().each {
println("- " + it.get())
}
}
} |
Are there any updates on this issue? This is quite a pain in a bigger project. |
Personally I would love to contribute a patch, but I need some guidance:
I am not investing more time into this until I get some feedback from the committers responsible for the gradle plugin. |
We might want to consider both, depending on the scope of the big change and how the small hack would look like.
Gradle ITs are in https://github.com/quarkusio/quarkus/tree/main/integration-tests/gradle. Given that the Quarkus project is Maven a project, Gradle ITs are actually launched from Maven. Meaning to run Gradle ITs from that module you could execute
The test projects are located under
|
To fix that, there's a bunch of code that needs to be touched. IMO Gradle's continuous build functionality should be used to build the project including its dependencies. The Quarkus Dev code parts need to be changed to only reload changed parts but never actually build code. I've started some work here, but haven't found time to continue on that (the code in that branch is hacky & messy). IIRC it could at least figure our the dependencies in a better way - but all the changes to the Quarkus Dev code are still missing. I don't mind if you want to pull some stuff from there. |
Right, Gradle continuous build would behind quarkusDev be the ultimate longer term goal. |
@aloubyansky does jmini@a426765 qualify as something that would be accepted? If yes I could turn my example project quarkus_issue35577 into an integration test that would be failing before my patch and green after. EDIT: the integration test part might be tricky since there is currently no tests testing |
@jmini yes, i think it would be acceptable. Thanks. |
There is a way to reproduce it with Currently failing with:
So I think I can use this for the integration test. The test case |
Sure, in case you are modifying an existing test, please make sure you are keeping the test for the original use-case. Thanks. |
Did we find way for contionous build not being triggered unless we had a request coming in? |
Gradle notifies „us“, when builds finish, including the artifacts that have been changed. Our plugin could forward the notification to the Quarkus process. The change in Quarkus-dev would be to only reload changed artifacts, but not trigger any build actions. |
Hi @jmini are you still trying to fix this issue? I'm also affected and I have time help! |
@clementguillot can you check if my patch jmini@889d634 would work for you? I can try to rebase it on head of the quarkus repo. |
@jmini sure, I will try on an existing multi-module Kotlin application |
I was able to rebase my patch on top of |
I was wondering why I could not reproduce the issue in the Usually the root gradle project does not contains any sources, sometimes you have sections like So despite the fact that there is no sources, if you add this to the root
The issue described here can't be reproduced. ^ I see this as a valid work-around. cc: @clementguillot 🤔 I did not exactly investigated why, but adding this in the top project modifies the behavior of the |
Thank you @jmini for your detailed answer. I have tested on my side and I can confirm that I'm only able to reproduce issue without plugin Once I globally add this plugin, everything works as expected, including hot reload. Many thanks for your help! |
@jmini : Did you try if it also works when you have the kotlin jvm plugin in the root gradle but mark it as apply(false)? The reason I'm asking is that we cannot apply this on top level because it would then apply to all submodules. This however, does not work together with Kotlin Multiplatform (which we use in our monorepo for the app of the service). |
@andreas-eberle it works and it fixes couple of warnings in IntelliJ and at build-time 😉 |
True, it looks like it works for a normal Kotlin module. Now I have one more thing... :D
|
Same problem here. I have a dependency on Kotlin Multiplatform module and the build is failing. Any suggestions how to workaround/fix this? I can share my project layout if interested. |
Workaround till this bug exists: I have two gradle modules. One has applied |
Describe the bug
I am in a multi-module gradle project.
:core-lib
shared lib@ApplicationScoped
):app1
quarkus app@Inject
to get the services from thecore-lib
In a real setup there are more modules (multiple shared modules, and multiple quarkus app that achieve different tasks of a more complex system)
Building the app and running it with
java -jar app1/build/quarkus-app/quarkus-run.jar
runs perfectly fine.Running with dev mode
./gradlew app1:quarkusDev
is failing:(complete trace at the bottom of this message)
The error is similar to when the jandex plugin in not running in
core-lib
(from the docs: Working with multi-module gradle projects).But this is not the case here. Jandex is configured and is working.
Also a work-around for kordamp/jandex-gradle-plugin#24 is in place.
But what is wired is that:
works perfectly.
Also when we build the docker image of the quarkus app, everything is working correctly.
And the issue is only present when the
core-lib
module contains kotlin code. With only java code everything works as expected.This is only a dev-mode issue.
How to Reproduce?
See repository:
https://github.com/jmini/quarkus_issue35577
Output of
uname -a
orver
macOS, but it doesn't matter.
We observe the same on Linux.
Output of
java -version
GraalVM version (if different from Java)
not relevant
Quarkus version or git rev
3.3.0 (reproducible as well with lower versions)
Build tool (ie. output of
mvnw --version
orgradlew --version
)Additional information
Complete error when running `./gradlew app1:quarkusDev`
I have tried to inspect the generated jandex file in
core-lib
(using a jbang script) and it looks OK (my classes and its annotation are present)Script to inspect the jandex index
Also when look at the trace logs of the Annotation Transformers (see docs), configured with:
I see only the line for the class written in java:
Nothing for the class written in Kotin, so it makes sense that it can not be injected later on.
The text was updated successfully, but these errors were encountered: