alternative extension dependency injection

36 views
Skip to first unread message

Alexey Loubyansky

unread,
Nov 1, 2021, 5:05:17 AM11/1/21
to quark...@googlegroups.com
Today we support conditional dependencies (in the extension metadata) that are optional dependencies which can be injected/activated in case a certain condition is satisfied. Their purpose could be described as "enable this extension if all its required dependencies appear to be available on the classpath".

Looking at PR [1] though decoupling quarkus-spring-web from RESTEasy Classic, which introduces a breaking change by requiring users to add either quarkus-resteasy-jackson or quarkus-resteasy-jackson-reactive, I had some thoughts about enhancing our support for conditional dependencies to make the end user experience better. Although, it would make the Quarkus dependency model even darker magic. Here is one idea anyway.

We could define extensions that appear to be alternative implementations of the same functionality/spec in the Quarkus platform properties, which is a platform-specific configuration [2] that is available during the dependency resolution phase. For example (perhaps, not a very a good one but to give an idea), it could look something like this:

resteasy.blocking=io.quarkus:quarkus-resteasy-blocking
resteasy.reactive=io.quarkus:quarkus-resteasy-reactive
# defines the default resteasy impl
dependency-injection.default.resteasy=${resteasy.reactive}
# defines the condition to be satisfied for the default impl to be injected
dependency-injection.if-none-available.resteasy=${resteasy.reactive},${resteasy.blocking}

Then the io.quarkus:quarkus-resteasy could become an injection point by adding the following to its metadata (META-INF/quarkus-extension.properties):

# inject the default resteasy impl unless one of its flavors is already present on the classpath
inject-dependencies=resteasy

For projects with complex dependency graphs though it may become less straightforward for users, and even us, to figure how the final dependency tree got resolved. Injecting one default may affect what other injection points will be initialized with (which isn't bad but may be hard to understand the injection sequence). There will also be the conditional dependencies that we support today in the mix. Besides making `mvn dependency:tree` useless and requiring `quarkus:dependency-tree` instead (which is already recommended today, the Gradle side should be ok though), there could be multiple injection points defaulting to incompatible alternatives. For example, there could be quarkus-resteasy defaulting to the reactive impl bringing the reactive impl of the Jackson serializer and there could be something else defaulting to the blocking impl of the Jackson serializer, for example. In this case, we'll need to choose which injection point to resolve first as that one will either break or force the non-default alternative for the other injection point. Which is generally ok but the question is which injection point should get the priority. This could be made consistent with the default dependency version convergence rules in the underlying built system. But it just shows how complicated it could become and what it would take to debug this.

WDYT? Is it worth exploring it further?

Georgios Andrianakis

unread,
Nov 1, 2021, 5:09:20 AM11/1/21
to Alexey Loubyansky, Quarkus Development mailing list
I can't comment on any of the mechanics because I have not looked into this part of Quarkus at all, but I definitely agree with the idea of providing a default when users have not picked one.
 
--
You received this message because you are subscribed to the Google Groups "Quarkus Development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to quarkus-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/quarkus-dev/CAJ97idFxz8c-nourjqAL9jXfxB9pxEyUdq-hX3Z4Jhv6uiab4w%40mail.gmail.com.

Stuart Douglas

unread,
Nov 1, 2021, 8:44:06 PM11/1/21
to Alexey Loubyansky, Quarkus Development mailing list
I think we need to be careful about how much complexity we add here.

Unless we have a reasonable number of compelling use cases then I don't think we should do this.

Stuart

--

Loïc MATHIEU

unread,
Nov 2, 2021, 5:12:15 AM11/2/21
to Stuart Douglas, Alexey Loubyansky, Quarkus Development mailing list
Hi,

I'm not comfortable to automatically (auto-magically) add dependencies. This will defeat the "declaractive approach" of Maven which is very important to me. It also add some security risks as tools basing on the declarative approach of Maven (like the OWASP dependency check Maven plugin wich is widely used or tools like Checkmarks) will rely on the presence of all the dependencies of the application inside the pom.xml.

If we want to automatically add dependency, we need to add them to the pom.xml. I'd rather add something to the dev mode to suggest dependencies to be added to the pom.xml (and Y/N the inclusion so the user can opt-in).

If you really want to automatically add dependencies under the cover, it should be optin/optout for security reasons.

Regards,

Loïc

KimJohn Quinn

unread,
Nov 2, 2021, 10:26:03 PM11/2/21
to Quarkus Development mailing list
Just wanted to through in my two sense because this exactly one of the main reasons we moved to Quarkus from SpringBoot - to reduce the "automagic" configurations especially when using AutoConfigurations. 

AutoConfiguration was a significant pain for us as our platform grew and it became harder and harder to manage/control/decipher.

Between the combination of "starters", optional dependencies, and opiniated injection I would rather have a fast fail because of a missing dependency and because I may not want a default, and in fact for it to fail, would prefer not to have any defaults.  The latter scenario comes into play when someone uses a component they are not meant to, if you fall back to a default it could automagically be wired in.

Max Rydahl Andersen

unread,
Nov 10, 2021, 5:36:30 PM11/10/21
to Alexey Loubyansky, quark...@googlegroups.com

I've read this a few times now and I agree with the sentiment and liking the
approach of the platform being able to "direct" the default dependencies.

That said; I think it is pushing the envelope too much and will break tools and
human assumptions in hard to spot places.

Could we instead of resolving automatically print out suggestions about dependencies
to add/remove for a better setup ?

/max

Reply all
Reply to author
Forward
0 new messages