Quarkus: Beans from transitive dependencies of a direct optional dependency are not injectable

Created on 7 Aug 2020  路  10Comments  路  Source: quarkusio/quarkus

Describe the bug
If a direct dependency of a Maven module is marked as optional, beans in transitive dependencies of this optional dependency are not injectable.

E.g.:

  • module core defines quarkus-liquibase (+ h2 and some other basic stuff)
  • module dist depends on core, but with <optional>true</optional>
  • module dist is injecting LiquibaseFactory in some bean (e.g. a resource class)
  • module dist is also injecting a bean from core

In this scenario, the bean from core is injectable, but LiquibaseFactory is not.

Expected behavior
Transitive deps of a direct optional dep are still injectable.
Only _transitive_ deps that are declared as optional should not be available/injectable (e.g. if core would mark quarkus-liquibase as optional)

Actual behavior
ArC fails:

Caused by: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type io.quarkus.liquibase.LiquibaseFactory and qualifiers [@Default]
        - java member: com.github.famod.modmono_quarkus.dist.HelloResource#liquibaseFactory
        - declared on CLASS bean [types=[com.github.famod.modmono_quarkus.dist.HelloResource, java.lang.Object], qualifiers=[@Default, @Any], target=com.github.famod.modmono_quarkus.dist.HelloResource]

To Reproduce
Steps to reproduce the behavior:

  1. git clone https://github.com/famod/modmono-quarkus
  2. git switch optional-problem
  3. mvn clean install (should fail in test with the mentioned exception)
  4. Note that there are _no_ classloading problems! Maven adds core and all its transitive deps to the classpath (which is correct as per spec).
  5. Remove @Inject from HelloResource.liquibaseFactory -> Test or DevMode will not fail anymore
  6. Put back @Inject but remove <optional> from dist/pom.xml -> Test or DevMode will not fail anymore

Configuration

quarkus.http.port=18080

quarkus.datasource.db-kind=h2
quarkus.datasource.username=sa
quarkus.datasource.password=sa
quarkus.datasource.jdbc.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

Environment (please complete the following information):

  • Output of uname -a or ver: MINGW64_NT-10.0-18363 XXX 3.0.7-338.x86_64 2019-11-21 23:07 UTC x86_64 Msys
  • Output of java -version: OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)
  • GraalVM version (if different from Java): n/a
  • Quarkus version or git rev: 1.6.1.Final
  • Build tool (ie. output of mvnw --version or gradlew --version): Apache Maven 3.6.3

Additional context

$ mvn org.apache.maven.plugins:maven-dependency-plugin:3.1.2:tree -f dist/
[INFO] Scanning for projects...
[INFO]
[INFO] -------< com.github.famod.modmono-quarkus:modmono-quarkus-dist >--------
[INFO] Building modmono-quarkus-dist 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ modmono-quarkus-dist ---
[INFO] com.github.famod.modmono-quarkus:modmono-quarkus-dist:jar:1.0-SNAPSHOT
[INFO] +- com.github.famod.modmono-quarkus:modmono-quarkus-core:jar:1.0-SNAPSHOT:compile (optional)
[INFO] |  +- jakarta.enterprise:jakarta.enterprise.cdi-api:jar:2.0.2:compile
[INFO] |  |  +- jakarta.el:jakarta.el-api:jar:3.0.3:compile
[INFO] |  |  +- jakarta.interceptor:jakarta.interceptor-api:jar:1.2.5:compile
[INFO] |  |  \- jakarta.inject:jakarta.inject-api:jar:1.0:compile
[INFO] |  +- io.quarkus:quarkus-jdbc-h2:jar:1.6.1.Final:compile (optional)
[INFO] |  |  +- com.h2database:h2:jar:1.4.197:compile (optional)
[INFO] |  |  \- org.locationtech.jts:jts-core:jar:1.15.0:compile (optional)
[INFO] |  \- io.quarkus:quarkus-liquibase:jar:1.6.1.Final:compile (optional)
[INFO] |     +- org.liquibase:liquibase-core:jar:3.10.0:compile (optional)
[INFO] |     +- org.yaml:snakeyaml:jar:1.26:compile (optional)
[INFO] |     +- io.quarkus:quarkus-jaxb:jar:1.6.1.Final:compile (optional)
[INFO] |     |  +- org.glassfish.jaxb:jaxb-runtime:jar:2.3.3-b02:compile (optional)
[INFO] |     |  |  +- org.glassfish.jaxb:txw2:jar:2.3.3-b02:compile (optional)
[INFO] |     |  |  \- com.sun.istack:istack-commons-runtime:jar:3.0.10:compile (optional)
[INFO] |     |  \- org.jboss.spec.javax.xml.bind:jboss-jaxb-api_2.3_spec:jar:2.0.0.Final:compile
[INFO] |     +- io.quarkus:quarkus-agroal:jar:1.6.1.Final:compile (optional)
[INFO] |     |  +- io.quarkus:quarkus-datasource:jar:1.6.1.Final:compile (optional)
[INFO] |     |  |  \- io.quarkus:quarkus-datasource-common:jar:1.6.1.Final:compile (optional)
[INFO] |     |  +- org.jboss.narayana.jta:narayana-jta:jar:5.10.5.Final:compile (optional)
[INFO] |     |  |  +- org.jboss:jboss-transaction-spi:jar:7.6.0.Final:compile (optional)
[INFO] |     |  |  \- org.jboss.spec.javax.resource:jboss-connector-api_1.7_spec:jar:1.0.0.Final:compile (optional)
[INFO] |     |  +- org.jboss.narayana.jts:narayana-jts-integration:jar:5.10.5.Final:compile (optional)
[INFO] |     |  +- jakarta.transaction:jakarta.transaction-api:jar:1.3.3:compile
[INFO] |     |  +- io.agroal:agroal-api:jar:1.8:compile (optional)
[INFO] |     |  +- io.agroal:agroal-narayana:jar:1.8:compile (optional)
[INFO] |     |  +- io.agroal:agroal-pool:jar:1.8:compile (optional)
[INFO] |     |  \- io.quarkus:quarkus-credentials:jar:1.6.1.Final:compile (optional)
[INFO] |     +- io.quarkus:quarkus-narayana-jta:jar:1.6.1.Final:compile (optional)
[INFO] |     |  +- io.quarkus:quarkus-mutiny:jar:1.6.1.Final:compile (optional)
[INFO] |     |  |  +- io.quarkus:quarkus-smallrye-context-propagation:jar:1.6.1.Final:compile (optional)
[INFO] |     |  |  |  \- io.smallrye:smallrye-context-propagation:jar:1.0.13:compile (optional)
[INFO] |     |  |  |     \- io.smallrye:smallrye-context-propagation-api:jar:1.0.13:compile (optional)
[INFO] |     |  |  \- io.smallrye.reactive:mutiny-context-propagation:jar:0.5.4:compile (optional)
[INFO] |     |  +- io.smallrye:smallrye-context-propagation-jta:jar:1.0.13:compile (optional)
[INFO] |     |  +- io.smallrye.reactive:smallrye-reactive-converter-api:jar:1.0.13:compile (optional)
[INFO] |     |  |  +- org.eclipse.microprofile.reactive-streams-operators:microprofile-reactive-streams-operators-api:jar:1.0.1:compile (optional)
[INFO] |     |  |  \- org.eclipse.microprofile.reactive-streams-operators:microprofile-reactive-streams-operators-core:jar:1.0.1:compile (optional)
[INFO] |     |  \- io.smallrye.reactive:smallrye-reactive-converter-mutiny:jar:1.0.13:compile (optional)
[INFO] |     \- org.osgi:org.osgi.core:jar:6.0.0:compile (optional)
[INFO] +- io.quarkus:quarkus-resteasy:jar:1.6.1.Final:compile
[...]

Notice the (optional), but all deps are on the classpath.

PS: The reproducer is rather silly. The real world setup in which we hit this problem makes more sense.

/cc @mickroll

aremaven kinbug

All 10 comments

@aloubyansky This is the one we discussed on zulip.

So to be more precise, extensions that are transitive dependencies of a direct optional dependency aren't effective.

I agree it should work.

Interesting, your reproducer doesn't seem to work with current master (with optional = false)

Sorry, it was an issue in my branch. It works :)

So to be more precise, extensions that are transitive dependencies of a direct optional dependency aren't effective.

I wasn't sure whether this is limited to extensions, didn't check.

That was based on this statement:

In this scenario, the bean from core is injectable, but LiquibaseFactory is not.

ah, you mean you didn't include non extension transitive deps.

@famod just fyi, i'm working on a fix here https://github.com/aloubyansky/quarkus/commit/8f1b33fdbf0b8e6444caa8c83ae9a7da9c1669f9 with this commit the tests pass. But the dev mode isn't working. I haven't yet looked why.

Was this page helpful?
0 / 5 - 0 ratings