Skip to content

dev mode is not working in a gradle multimodule setup when kotlin code is used #35577

Open
@jmini

Description

Describe the bug

I am in a multi-module gradle project.

  • :core-lib shared lib
    • contains java and kotlin code (classes annotated with @ApplicationScoped)
    • jandex plugin is configured
    • kotlin for quarkus is configured (incl. the allopen plugin)
  • :app1 quarkus app
    • contains a Rest endpoint using @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:

jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.core.kt.ConfigService and qualifiers [@Default]
        - java member: org.acme.app1.App1Controller#config
        - declared on CLASS bean [types=[org.acme.app1.App1Controller, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.app1.App1Controller]
        at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:477)
        at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:624)
        at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:299)
... 

(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:

./gradlew (clean) build
java -jar app1/build/quarkus-app/quarkus-run.jar

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 or ver

22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023; root:xnu-8792.81.3~2/RELEASE_X86_64 x86_64

macOS, but it doesn't matter.

We observe the same on Linux.

Output of java -version

openjdk version "17.0.5" 2022-10-18
OpenJDK Runtime Environment Temurin-17.0.5+8 (build 17.0.5+8)
OpenJDK 64-Bit Server VM Temurin-17.0.5+8 (build 17.0.5+8, mixed mode, sharing)

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 or gradlew --version)

------------------------------------------------------------
Gradle 8.1.1
------------------------------------------------------------

Build time:   2023-04-21 12:31:26 UTC
Revision:     1cf537a851c635c364a4214885f8b9798051175b

Kotlin:       1.8.10
Groovy:       3.0.15
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.5 (Eclipse Adoptium 17.0.5+8)
OS:           Mac OS X 13.2.1 x86_64

Additional information

Complete error when running `./gradlew app1:quarkusDev`
2023-08-26 13:38:06,883 INFO  [io.qua.dep.dev.IsolatedDevModeMain] (main) Attempting to start live reload endpoint to recover from previous Quarkus startup failure
> :ap2023-08-26 13:38:07,507 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
        [error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: jakarta.enterprise.inject.spi.DeploymentException: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.core.kt.ConfigService and qualifiers [@Default]
        - java member: org.acme.app1.App1Controller#config
        - declared on CLASS bean [types=[org.acme.app1.App1Controller, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.app1.App1Controller]
        at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:1447)
        at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:311)
        at io.quarkus.arc.processor.BeanProcessor.initialize(BeanProcessor.java:158)
        at io.quarkus.arc.deployment.ArcProcessor.validate(ArcProcessor.java:469)
        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 io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:858)
        at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
        at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
        at java.base/java.lang.Thread.run(Thread.java:833)
        at org.jboss.threads.JBossThread.run(JBossThread.java:501)
Caused by: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.core.kt.ConfigService and qualifiers [@Default]
        - java member: org.acme.app1.App1Controller#config
        - declared on CLASS bean [types=[org.acme.app1.App1Controller, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.app1.App1Controller]
        at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:477)
        at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:624)
        at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:299)
        ... 13 more

        at io.quarkus.runner.bootstrap.AugmentActionImpl.runAugment(AugmentActionImpl.java:336)
        at io.quarkus.runner.bootstrap.AugmentActionImpl.createInitialRuntimeApplication(AugmentActionImpl.java:253)
        at io.quarkus.runner.bootstrap.AugmentActionImpl.createInitialRuntimeApplication(AugmentActionImpl.java:60)
        at io.quarkus.deployment.dev.IsolatedDevModeMain.firstStart(IsolatedDevModeMain.java:82)
        at io.quarkus.deployment.dev.IsolatedDevModeMain.accept(IsolatedDevModeMain.java:423)
        at io.quarkus.deployment.dev.IsolatedDevModeMain.accept(IsolatedDevModeMain.java:55)
        at io.quarkus.bootstrap.app.CuratedApplication.runInCl(CuratedApplication.java:138)
        at io.quarkus.bootstrap.app.CuratedApplication.runInAugmentClassLoader(CuratedApplication.java:93)
        at io.quarkus.deployment.dev.DevModeMain.start(DevModeMain.java:131)
        at io.quarkus.deployment.dev.DevModeMain.main(DevModeMain.java:62)
Caused by: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
        [error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: jakarta.enterprise.inject.spi.DeploymentException: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.core.kt.ConfigService and qualifiers [@Default]
        - java member: org.acme.app1.App1Controller#config
        - declared on CLASS bean [types=[org.acme.app1.App1Controller, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.app1.App1Controller]
        at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:1447)
        at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:311)
        at io.quarkus.arc.processor.BeanProcessor.initialize(BeanProcessor.java:158)
        at io.quarkus.arc.deployment.ArcProcessor.validate(ArcProcessor.java:469)
        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 io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:858)
        at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
        at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
        at java.base/java.lang.Thread.run(Thread.java:833)
        at org.jboss.threads.JBossThread.run(JBossThread.java:501)
Caused by: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.core.kt.ConfigService and qualifiers [@Default]
        - java member: org.acme.app1.App1Controller#config
        - declared on CLASS bean [types=[org.acme.app1.App1Controller, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.app1.App1Controller]
        at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:477)
        at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:624)
        at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:299)
        ... 13 more

        at io.quarkus.builder.Execution.run(Execution.java:123)
        at io.quarkus.builder.BuildExecutionBuilder.execute(BuildExecutionBuilder.java:79)
        at io.quarkus.deployment.QuarkusAugmentor.run(QuarkusAugmentor.java:160)
        at io.quarkus.runner.bootstrap.AugmentActionImpl.runAugment(AugmentActionImpl.java:332)
        ... 9 more
Caused by: jakarta.enterprise.inject.spi.DeploymentException: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.core.kt.ConfigService and qualifiers [@Default]
        - java member: org.acme.app1.App1Controller#config
        - declared on CLASS bean [types=[org.acme.app1.App1Controller, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.app1.App1Controller]
        at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:1447)
        at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:311)
        at io.quarkus.arc.processor.BeanProcessor.initialize(BeanProcessor.java:158)
        at io.quarkus.arc.deployment.ArcProcessor.validate(ArcProcessor.java:469)
        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 io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:858)
        at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
        at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
        at java.base/java.lang.Thread.run(Thread.java:833)
        at org.jboss.threads.JBossThread.run(JBossThread.java:501)
Caused by: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.core.kt.ConfigService and qualifiers [@Default]
        - java member: org.acme.app1.App1Controller#config
        - declared on CLASS bean [types=[org.acme.app1.App1Controller, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.app1.App1Controller]
        at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:477)
        at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:624)
        at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:299)
        ... 13 more

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
///usr/bin/env jbang "$0" "$@" ; exit $?

//DEPS io.smallrye:jandex:3.1.2
//JAVA 17

import java.io.FileInputStream;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.Index;
import org.jboss.jandex.IndexReader;

public class JandexMain {
    public static void main(String[] args) throws Exception {
        try (FileInputStream input = new FileInputStream("core-lib/build/resources/main/META-INF/jandex.idx")) {
            IndexReader reader = new IndexReader(input);
            Index index = reader.read();

            // java.util.Collection<ClassInfo> knownClasses = index.getKnownClasses();
            // System.out.println(knownClasses.size());
            // for (ClassInfo classInfo : knownClasses) {
            //     System.out.println(classInfo.name());
            // }

            System.out.println("--- org.acme.core.CoreProcessor");
            ClassInfo reportingService = index.getClassByName("org.acme.core.CoreProcessor");
            for (AnnotationInstance a : reportingService.annotations()) {
                System.out.println(a.name());
            }

            System.out.println("--- org.acme.core.kt.ConfigService");
            ClassInfo foo = index.getClassByName("org.acme.core.kt.ConfigService");
            for (AnnotationInstance a : foo.annotations()) {
                System.out.println(a.name());
            }
        }
    }
}

Also when look at the trace logs of the Annotation Transformers (see docs), configured with:

quarkus.log.category."io.quarkus.arc.processor".min-level=TRACE
quarkus.log.category."io.quarkus.arc.processor".level=TRACE

I see only the line for the class written in java:

2023-08-26 13:56:06,883 TRACE [io.qua.arc.pro.BeanDeployment] (build-17) Created CLASS bean [types=[java.lang.Object, org.acme.core.CoreProcessor], qualifiers=[@Default, @Any], target=org.acme.core.CoreProcessor]

Nothing for the class written in Kotin, so it makes sense that it can not be injected later on.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions