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

Support the Concept of @ActiveProfile from Spring CDI #6814

Closed
sherl0cks opened this issue Jan 27, 2020 · 11 comments
Closed

Support the Concept of @ActiveProfile from Spring CDI #6814

sherl0cks opened this issue Jan 27, 2020 · 11 comments
Labels
area/arc Issue related to ARC (dependency injection) area/spring Issues relating to the Spring integration kind/enhancement New feature or request
Milestone

Comments

@sherl0cks
Copy link
Contributor

sherl0cks commented Jan 27, 2020

Description
Spring Profiles are very different than Quarkus Profiles. The former is focused on decomposing your DI config into subsets, and the later is focused on environment specific config properties.

The most useful part of Spring Profiles is the ability to annotate a test with @ActiveProfile("SomeProfile"), which will instruct the DI system to only spin up beans with that profile. This is very helpful for tests written against an API, e.g. JPA. I may have two profiles "postgres" and "hsql", and depending on the test, I will want to spin up one or the other, but not both. Today's @QuarkusTest will spin up the entire CDI config and there is no way to spin up a subset. User must use @ApplicationScoped for lazy evaluation.

You can kind of assemble this "Profile" concept using CDI qualifiers like @Named and @Typed and @Alternative, but it would be really nice to have @Profile and @ActiveProfileas first order concepts.

See discussion in https://quarkusio.zulipchat.com/#narrow/stream/187030-users/topic/configuring.20Mocks.20in.20.40QuarkusTest

Implementation ideas
It would be nice to have this added as an ArC extensions like the CDI oriented convenience features in ArC. The Spring DI extension would work as well.

@sherl0cks sherl0cks added the kind/enhancement New feature or request label Jan 27, 2020
@geoand geoand added area/spring Issues relating to the Spring integration area/arc Issue related to ARC (dependency injection) labels Jan 27, 2020
@geoand
Copy link
Contributor

geoand commented Jan 27, 2020

cc @mkouba @manovotn

@mkouba
Copy link
Contributor

mkouba commented Jan 28, 2020

I like the idea but there are some problems we would need to resolve first:

  1. Our DI is build-time oriented, ie. injection points are resolved/validate at build time. And the applications is only built/started once for the whole test suite. In other words, currently we can't activate a different "DI profile" per @QuarkusTest.
  2. We would have to (1) merge this feature with "Configuration Profiles", otherwise users might be confused or (2) use a different name.

@dmlloyd @emmanuelbernard Any ideas?

@manovotn
Copy link
Contributor

manovotn commented Jan 28, 2020

I've see the Zulip discussion yesterday.
In pure CDI you usually deal with this via alternatives enabled only in test environments (which basically allows you to mock whichever beans you want to). Here, you would need a combination of @DefaultBean and then another impl in the test itself. For smaller apps that would work but if you have something huge, it can see how this becomes a pain.

Our DI is build-time oriented, ie. injection points are resolved/validate at build time.

I agree this is the problematic part.

Couldn't we "cheat it" by making the new annotation (@ActiveProfile?) a qualifiers that all beans have (just like `@Any) and then make its value non-binding? In such way it wouldn't interfere with bean resolution that user requires but we could still leverage that while building the deployment. E.g. get the profile value during build from config and based on that only generate beans which have that value? Just a quick thought, not sure if it would work :-)
WDYT @mkouba ?

@mkouba
Copy link
Contributor

mkouba commented Jan 28, 2020

Couldn't we "cheat it" by making the new annotation a qualifier...

In that case the injection points would have to declare the qualifier as well...

@manovotn
Copy link
Contributor

Not sure I follow.., the typesafe resolution says the bean is assignable if it has all the qualifiers that the injection point requires. Surplus qualifiers don't matter - just like we handle it with @Any which is on every bean, yet you rarely use that on an injection point. Or am I missing something?

@mkouba
Copy link
Contributor

mkouba commented Jan 28, 2020

Well, if an injection point has no qualifier then it's defaulted -> @Default and all beans that have this qualifier are eligible. Therefore, if you have a bean with qualifier @Profile("foo") it is not eligible for this injection point.

just like we handle it with @Any which is on every bean, yet you rarely use that on an injection point.

Indeed, because this would result in an ambiguous exception if multiple beans of the given type exist. It's mostly used for @Inject Instance<>...

@manovotn
Copy link
Contributor

manovotn commented Jan 28, 2020

Well, if an injection point has no qualifier then it's defaulted -> @default

Aah, I see what you mean! That's a fair point, I forgot about default...
We'd have to add @Default even if there was @Profile, effectively making @Profile "invisible" for resolution. At which point we might as well not have it as qualifiers but instead as usual annotation that we check for and based on its value we either generate that bean's metadata or we don't (which isn't 100% correct either and would require all alternative impl of given bean to have that annotation).

@sherl0cks
Copy link
Contributor Author

sherl0cks commented Jan 28, 2020

Merging with the existing quarkus profiles concept makes sense to me. A user on Zulip was using the profiles manager to get the current profile and use it to drive a switch statement in a dynamic producer method, so there there is evidence users already come to this conclusion.

it seems to me that the core issue here is that @QuarkusTest MUST spin up the whole context and there is no notion of multiple contexts. I’m not a CDI expert, but that seems limiting as a long time spring user. That said, I realize the trade off here with build time resolution.

Perhaps in the short term documentation is the solution? The approach I came to feels pretty solid and basically achieves the same effect as profiles, but within existing CDI / quarkus annotations. If reading the config guide or a google search would have yielded my strategy , it would have saved me 2 days of frustration and nearly removing CDI entirely from the app.

@mkouba
Copy link
Contributor

mkouba commented Jan 29, 2020

Perhaps in the short term documentation is the solution?

Would you care to send a PR? ;-)

The testing guide: https://github.com/quarkusio/quarkus/blob/master/docs/src/main/asciidoc/getting-started-testing.adoc

@sherl0cks
Copy link
Contributor Author

@mkouba I'd love to, but unclear when I could make it a priority. I’ll circle back on this next week.

@geoand
Copy link
Contributor

geoand commented Apr 6, 2020

In #8343 we added @IfBuildProfile and @UnlessBuildProfile which I think covers this use case.

@geoand geoand closed this as completed Apr 6, 2020
@geoand geoand added this to the 1.4.0 milestone Apr 6, 2020
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) area/spring Issues relating to the Spring integration kind/enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants