Skip to content
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

Make @DefaultBean work with @Priority #37042

Closed
gwenneg opened this issue Nov 13, 2023 · 8 comments · Fixed by #37075
Closed

Make @DefaultBean work with @Priority #37042

gwenneg opened this issue Nov 13, 2023 · 8 comments · Fixed by #37075
Assignees
Labels
area/arc Issue related to ARC (dependency injection) kind/enhancement New feature or request
Milestone

Comments

@gwenneg
Copy link
Member

gwenneg commented Nov 13, 2023

Description

Let's say I work on a small framework which can be used by an application by depending on several different dependencies (framework-core or framework-advanced), based on the application needs.

The framework-core dependency contains these two classes:

@ApplicationScoped
@DefaultBean
public class CoreFeature {
    // Details omitted, not relevant
}

@ApplicationScoped
public class InternalFrameworkService {

    @Inject
    CoreFeature coreFeature;

    // coreFeature is used somehow.
}

The framework-advanced dependency depends on framework-core and contains this class:

@ApplicationScoped
@DefaultBean
public class AdvancedFeature extends CoreFeature {
    // Details omitted, not relevant
}

Right now, when an app depends on framework-advanced, Arc will complain because it cannot determine which of CoreFeature and AdvancedFeature should be injected in InternalFrameworkService. I would like this to work using @Priority on CoreFeature and AdvancedFeature so that Arc injects the one with the highest priority, just like it does with @Alternative.

Why do I need @DefaultBean? Because I want the users of the framework to be able to do this:

@ApplicationScoped
public class UserCustomizedCoreFeature extends CoreFeature {
    // Details omitted, not relevant
}

Or that:

@ApplicationScoped
public class UserCustomizedAdvancedFeature extends AdvancedFeature {
    // Details omitted, not relevant
}

And override anything that comes from the framework with whatever they need to implement.

This whole thing can work without @Priority working with @DefaultBean, but the users of the framework have to use @Alternative alongside with @Priority on their class, which is something I'd like to avoid.

Implementation ideas

Make @DefaultBean and @Priority work similarly to @Alternative and @Priority.

@gwenneg gwenneg added the kind/enhancement New feature or request label Nov 13, 2023
@gwenneg gwenneg added area/arc Issue related to ARC (dependency injection) and removed triage/needs-triage labels Nov 13, 2023
Copy link

quarkus-bot bot commented Nov 13, 2023

/cc @Ladicek (arc), @manovotn (arc), @mkouba (arc)

@manovotn
Copy link
Contributor

Why do I need @DefaultBean? Because I want the users of the framework to be able to do this:

Note that if user defines their own bean extending AdvancedFeature, it will override both your default beans as it will have bean types of both AdvancedFeature, and CoreFeature.

Apart from the obvious approach of adding the priority functionality, two things come to my mind.

  1. As for this piece of code:
@ApplicationScoped
@DefaultBean
public class AdvancedFeature extends CoreFeature {
    // Details omitted, not relevant
}

One thing you could do is add @Typed(AdvancedFeature.class) to your default implementation. That way Arc won't be confused as there would be only one default bean per each type.

  1. In your framework-advanced, you could look into vetoing the original default bean (CoreFeature) because anyone using this dependency can instead leverage the default bean for AdvancedFeature.

@mkouba
Copy link
Contributor

mkouba commented Nov 13, 2023

2. In your framework-advanced, you could look into vetoing the original default bean (CoreFeature) because anyone using this dependency can instead leverage the default bean for AdvancedFeature.

Yes, if framework-advanced is a quarkus extension then "vetoing" the CoreFeature is a reasonable solution; either with ExcludedTypeBuildItem or with AnnotationsTransformerBuildItem + add @Vetoed to the CoreFeature.

But overall I think that it's a good idea to support multiple default beans sorted by priority.

@Ladicek
Copy link
Contributor

Ladicek commented Nov 13, 2023

The feature request kinda makes sense, when you think of @DefaultBean as a reversed @Alternative. An alternative takes precedence over "normal" bean, and a "normal" bean takes precedence over "default bean".

@manovotn
Copy link
Contributor

Right, I am not against it either, just trying to help find a solution using what we already have :)

BTW, if we want to add this, we could also just add the priority directly as a value on the @DefaultBean annotation (with some default).

@Ladicek
Copy link
Contributor

Ladicek commented Nov 13, 2023

We got rid of @AlternativePriority for a good reason, I wouldn't be a fan of sneaking something like that back :-)

Ah and yes, I agree vetoing CoreFeature is a good option for now.

@gwenneg
Copy link
Member Author

gwenneg commented Nov 13, 2023

Thanks everyone for the answers and suggestions!

Unfortunately, the framework I mentioned is not a Quarkus extension, so vetoing is not an option.

@manovotn manovotn self-assigned this Nov 13, 2023
@manovotn
Copy link
Contributor

Unfortunately, the framework I mentioned is not a Quarkus extension, so vetoing is not an option.

You might be able to achieve the same via CDI extension, in CDI Lite those are build compatible extensions and you can use the @Enhancement phase to add @Vetoed annotation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/arc Issue related to ARC (dependency injection) kind/enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants