Description
When using mocks defined as alternatives using a QuarkusTestProfile
, quarkus prints an info for all beans declared as @Alternative
but not selected.
For instance if I am using @Alternative MockGreetingResource1
in test GreetingResource1Test
, and @Alternative MockGreetingResource2
in test GreetingResource2Test
, then GreetingResource1Test
will complain about MockGreetingResource2
and GreetingResource2Test
will complain about MockGreetingResource1
.
Granted it is not a warning, but it is noise at the beginning of the tests. may be that should be a DEBUG
instead of an INFO
.
exampe code (repeat for test and mock 2):
@QuarkusTest
@TestProfile(GreetingResource1Test.MyProfile.class)
public class GreetingResource1Test {
@Test
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("hello from mock1"));
}
public static class MyProfile implements QuarkusTestProfile {
@Override
public Set<Class<?>> getEnabledAlternatives() {
return Set.of(MockGreetingResource1.class);
}
}
}
and the associated log for a successful test:
2020-11-13 11:59:21,219 INFO [io.qua.arc.pro.Beans] (build-19) Ignoring bean defined via org.acme.getting.started.MockGreetingResource2 - declared as an @Alternative but not selected by @Priority, @AlternativePriority or quarkus.arc.selected-alternatives
2020-11-13 11:59:23,453 INFO [io.quarkus] (main) Quarkus 1.9.2.Final on JVM started in 5.178s. Listening on: http://0.0.0.0:8081
2020-11-13 11:59:23,454 INFO [io.quarkus] (main) Profile test activated.
2020-11-13 11:59:23,454 INFO [io.quarkus] (main) Installed features: [cdi, config-yaml, mutiny, resteasy, smallrye-context-propagation]
2020-11-13 11:59:27,275 INFO [io.quarkus] (main) Quarkus stopped in 0.085s
/cc @Ladicek, @cescoffier, @jmartisk, @jponge, @kenfinnigan, @manovotn, @mkouba, @phillip-kruger, @radcortez
Hmm, so basically using test profile reports false positives because we encourage people to declare profile-specific beans as just @Alternative
without @Priority
which is any other setting than this is almost certainly a user error.
Moving this logging to debug won't really solve it, IMO the INFO should be visible to warn about those use errors, but we may want to think of a way to exclude test alternatives that are dedicated to profiles. But I am not quite sure how...
With the information we have when we process the to-be-bean class, we don't have enough information to determine if it belong to any other (currently disabled) test profile.
@mkouba @geoand any ideas? The only thing I can think of is another annotation (extending Alternative
with an attribute) and I don't like it one bit :-D
Well, the result of QuarkusTestProfile.getEnabledAlternatives()
is transformed into quarkus.arc.selected-alternatives=...
but since your mock classes are accessible in all test profiles the log message is printed (e.g. GreetingResource1Test
enables MockGreetingResource1
but MockGreetingResource2
is part of the deployment as well).
How about if we simply make the log a debug log only in the test profile and when quarkus.arc.selected-alternatives
is set?
How about if we simply make the log a debug log only in the test profile and when quarkus.arc.selected-alternatives is set?
Hm, we could try to use the DEBUG level if LaunchMode == TEST
and quarkus.arc.selected-alternatives
is set but I'm not sure about the test profile...
Yeah, that's what I meant
OK, I can do that... soonish.
ideally you would want to print a warning for such classes if they come from src/main/java
, but not if they come from /src/test/java, regardless of the
LaunchMode`. because it would be nice to report a warning, even in test mode, if you find a class like this in the production code.
but may be you cannot distinguish the origin of classes (main vs test). so an acceptable compromise would be, like you said earlier, to deactivate this warning when running the tests.
Can someone explain this to me please? Why would it be an error to declare a bean as @Alternative
without @Priority
? This is perfectly normal, isn't it?
Can someone explain this to me please? Why would it be an error to declare a bean as @Alternative without @Priority? This is perfectly normal, isn't it?
@Priority
, the message lists all the ways how to select an alternative bean in quarkus: _"@Alternative but not selected by @Priority
, @AlternativePriority
or quarkus.arc.selected-alternatives
"_ideally you would want to print a warning for such classes if they come from src/main/java, but not if they come from /src/test/java
@vsevel Yes, I don't think there is an elegant (and build tool agnostic) way to distinguish the origin...
@gavinking it's not an error, we log an INFO message because if you add an alternative bean that in not selected we can be sure that this bean will never be used and it's very likely a user error (quarkus DI == build-time).
Well, I understand that Quarkus is build-time, but I still don't see why you couldn't have unused @Alternative
s in your build path. I mean, isn't that essentially the whole point of @Alternative
? (Perhaps I'm missing something.)
So I would say it's possibly an error, but I wouldn't say it's very likely.
And I gotta agree that logging a possible user error at INFO level is pretty obnoxious. Perhaps if it were one error message for all unused beans. But one per bean seems wrong.
It's not only about
@Priority
, the message lists all the ways how to select an alternative bean in quarkus: "@alternative but not selected by @Priority, @AlternativePriority or quarkus.arc.selected-alternatives
"
Excuse me, my bad, I was reading on the iPad GitHub app and didn't see the whole text of the message. That's better. I assume that quarkus.arc.selected-alternatives
is the way to do the equivalent of enabling alternatives in beans.xml
, right?
but I still don't see why you couldn't have unused @Alternatives in your build path.
But you could ;-). The primary purpose of this INFO message is to give a user a hint that some alternative bean that could be selected via beans.xml
or by some extension-based technique is ignored.
I mean, isn't that essentially the whole point of @Alternative?
I don't think so. The main use case for alternatives in quarkus is to provide an alternative implementation of a bean. Having an unselected alternative bean in a quarkus app is _pointless_, such a bean is simply ignored.
Note that in regular CDI apps alternatives can be added/resolved at runtime, e.g. if you add a jar to the class path and this jar contains an alternative bean. This is not the case for quarkus.
That's better. I assume that quarkus.arc.selected-alternatives is the way to do the equivalent of enabling alternatives in beans.xml, right?
Yes, exactly. But it's a config property that is fixed at build time.
Hm, we could try to use the DEBUG level if LaunchMode == TEST and quarkus.arc.selected-alternatives is set but I'm not sure about the test profile...
@mkouba BTW this will still hide actual user errors when running tests. In such case I think it's lesser evil to print some info logging about extra test-only alternatives rather than hide everything under debug. WDYT?
ideally you would want to print a warning for such classes if they come from src/main/java, but not if they come from /src/test/java
Yes, I don't think there is an elegant (and build tool agnostic) way to distinguish the origin...
I've just rediscovered the TestClassPredicateBuildItem
(ok, ok, I implemented this build item long time ago.. :-) and so we can actually distinguish the test classes.
BTW this will still hide actual user errors when running tests. In such case I think it's lesser evil to print some info logging about extra test-only alternatives rather than hide everything under debug. WDYT?
@manovotn Well, you're right that a log message does not hurt (esp. with the INFO level). I'll try to prepare a PR and then we can decide...
Ok, so I've created this - in this PR we log at DEBUG level for test classes and INFO for application/fwk classes. And I think that it's quite a reasonable behavior. @manovotn @geoand @vsevel WDYT?
I disagree. There's all sorts of reasons I might have a disabled @Alternative
in my app. Perhaps I have a second @Alternative
that inherits it, for example.
I really don't think you've got this quite right, unless I'm missing something very special about ArC compared to regular CDI.
And note that @Alternative
in "regular" CDI has almost nothing to do with adding things at runtime! That's not the purpose at all. It's about being able to select an implementation via configuration, which is typically done prior to building the whole application, though it might happen after building the library that contains an @Alternative
.
And note that @alternative in "regular" CDI has almost nothing to do with adding things at runtime! That's not the purpose at all. It's about being able to select an implementation via configuration...
Nobody says that alternatives are a "runtime thing". If you want to include several @Alternative
bean implemenations and select one per an application build then no problem, you can do that. This issue is only about logging a simple INFO log message. Nothing more.
So, I mean, it seems to me that either it's an actual error, and you should throw, or it's something that is actually reasonable in some circumstances and logging a noisy INFO is just not justified. The developer probably won't even notice the INFO, and instead what happens is you just accumulate noisy and useless log messages that annoy the poor soul who has to maintain this app in production.
So I think you should make up your mind if it's an error.
Nobody says that alternatives are a "runtime thing".
Well, you said it, above:
Note that in regular CDI apps alternatives can be added/resolved at runtime
I was responding to that comment.
This issue is only about logging a simple INFO log message.
Which is never the right way to communicate to developers.
Note that in regular CDI apps alternatives can be added/resolved at runtime
I was responding to that comment.
Well, it reads can be added/resolved at runtime not that it's "runtime only" or "runtime mainly"...
This issue is only about logging a simple INFO log message.
Which is never the right way to communicate to developers.
I disagree.
So, I mean, it seems to me that either it's an actual _error_, and you should throw, or it's something that is actually reasonable in some circumstances and logging a noisy INFO is just not justified. The developer probably won't even notice the INFO, and instead what happens is you just accumulate noisy and useless log messages that annoy the poor soul who has to maintain this app in production.
In cases like this one where you are just trying to convey a message that the user _might_ have made a mistake as there are multiple options available, what would be the alternative other than logging an info message?
Throwing an error seems too heavy handed to me.
Actually let me please be a bit long winded about this, because it's important, and it's a principle that underlies almost all our developer-facing APIs.
These are the (only) ways we inform developers of their errors, from highest preference to lowest preference:
I no case do we report bugs like this using log messages, since developers simply won't notice them at development time, and they're not useful when the software is in production. People hate noisy frameworks that report too much in the log at startup. This is a misuse of the log, which simply isn't intended for this purpose.
(FTR even Hibernate is much too noisy, IMO.)
Throwing an error seems too heavy handed to me.
I agree. As I said from the start, I think that this is a perfectly legit situation, and I see no justification for an error, nor an INFO-level log message. I'm perfectly fine if you log it at DEBUG level, but I suspect that's also pretty useless. (Developers use breakpoints for troubleshooting, not trawling the log.) If you want to be friendly to developers, expose an API which lets them easily obtain a list of enabled beans and other meta-stuff.
If you want to be friendly to developers, expose an API which lets them easily obtain a list of enabled beans and other meta-stuff.
FWIW, such an API does exist, in the form of the http://localhost:8080/quarkus/arc/beans
when running dev-mode.
I agree that a log message during application build is probably going to go unnoticed. I just tend to think that it's better than not having it at all.
In cases like this one where you are just trying to convey a message that the user might have made a mistake as there are multiple options available, what would be the alternative other than logging an info message?
The alternative is that you have a well-defined programming model where it is clear what is allowed and what is a mistake! Well-defined APIs don't go trying to guess if the user made a mistake according to hand-wavy heuristics! Nowhere in the CDI spec does it say:
"oh the library should print a whiney and annoying log message if the user does something that might maybe possibly be an error"
No no no, we _never_ define programming models in that way. Instead we enumerate the things which are incorrect and produce an error.
FWIW, such an API does exist
Then that's all I need to discover that my bean isn't being picked up.
I agree that a log message during application build is probably going to go unnoticed. I just tend to think that it's better than not having it at all.
Nope, it's worse. Because it will probably survive into production. And the log exists to discover production problems.
Nope, it's worse. Because it will probably survive into production. And the log exists to discover _production_ problems.
In the context of runtime messages, I completely agree.
But what about messages that are only logged during build? I mean a user would only see the info message in question during mvn package
, not when running the application.
In any case, I have no problem in making the message debug by default for all cases.
Well, OK sure, a build-time message is, I agree, less obnoxious. However, lots of people still build the app who are not developers, or not developers of the particular component that contains the disabled alternative bean.
And, as I've shown above, there are completely reasonable motivations for having a disabled alternative bean in the program, or in the libraries my program builds against. You don't want to go showing a complainy log message to everyone who builds the program, especially in the case that it's there for a completely good reason!
:+1:
the original issue was only related to the test use case, where using @Alternative
beans is a documented approach to mocking production code, with the option of limiting usage to a particular test. by definition, the INFO
is a false positive. logging this in debug, or not all is acceptable to me.
most of the late conversation seems to revolve around the production use case. the question again is whether or not having non selected alternatives is 1) a perfectly valid use case 2) an error 3) a smell.
for the third situation, ideally you would want to augment your programming model to make it deterministic (it is either valid or not). if not possible and if the underlying framework is non trivial to set up (and an injection engine usually is as there is magic involved), logging in debug mode with a special documented logger (e.g. _io.quarkus.arc.resolution_) may be an option. that way if something does not work the way you were expecting, you can turn that special logger on and get an explanation. those explanations should be at decision points (e.g. we chose that bean over that one because it has a higher priority), or at the end of the initialization phase. this should help diagnose, understand and remedy an unexpected behavior. it is similar in intent with the arc/beans
endpoint, but may allow to provide finer explanations (with more verbosity) and will work also with @QuarkusMain
applications.
ideally you would want to augment your programming model to make it deterministic (it is either valid or not)
Unfortunately, it's not always so clear.
@Alternative
bean which is not explicitly selected globally via @Priority
can be (1) selected locally via beans.xml
, (2) selected globally via an extension SPI (e.g. add @Priority
to the AnnotatedType
or via AfterTypeDiscovery
) and finally (3) unselected and thus ignored. (1) and (2) are not possible in Quarkus. We don't support portable extensions, we don't parse the beans.xml
descriptors and finally, we have a single "bean archive". And so if your application contains such an @Alternative
bean we log an INFO message because we cannot easily detect (1) and (2).If you guys outvote me I'm ready to update the PR.
I don't think we should spend more time on this issue. We have a solution to eliminate the test-related false positives
this sounds good to me. this addresses the original issue.
If you guys outvote me I'm ready to update the PR.
I don't mind either way
If you guys outvote me I'm ready to update the PR.
I have requested changes on the original PR.
I designed CDI based on a set of clear principles, and I don't want to see those undermined.
P.S. If you really think warning the developer about this condition is actually something that is important and necessary, then there is a correct and principled way to do it. You should stop the build with an exception, and then given the developer a way to "whitelist" the particular disabled bean you're warning them about. (Via a disabled_beans
property or whatever.)
That way you:
That is to say, instead of responding to uncertainly by doing something wishy-washy and heuristic, you remove the uncertainty by requiring the user to be explicit.
Now, I don't think that's necessary here, since I don't think it's sufficiently probable that a disabled @Alternative
bean is a bug. But if _you_ think it is, then that's the way to handle the problem _correctly_.
I am +1 for Martin's original solution of reducing the noice for tests only.
Working on CDI for several years and knowing how you can(not) enable an alternative in Quarkus, I would estimate that, in non-test code, you have 90+% chance of this alternative without priority being a user error.
P.S. If you really think warning the developer about this condition is actually something that is important and necessary, then there is a correct and principled way to do it. You should stop the build with an exception, and then given the developer a way to "whitelist" the particular disabled bean you're warning them about. (Via a
disabled_beans
property or whatever.)That way you:
- ensure that the developer _notices_ the problem, and
- Don't print useless messages to the log in the case that there's a good reason for having the disabled bean there.
That is to say, instead of responding to uncertainly by doing something wishy-washy and heuristic, you remove the uncertainty by requiring the user to be explicit.
Now, I don't think that's necessary here, since I don't think it's sufficiently probably that a disabled
@Alternative
bean is a bug. But if _you_ think it is, then that's the way to handle the problem _correctly_.
Or you could twist this around and say that we keep the logging and instead let the user explicitly disable it by using something like the property you suggested. So if they consider it annoying, they have a way to shut it down. But in most cases the log message can save someone a headache of figuring out what is going on with their app.
I designed CDI based on a set of clear _principles_, and I don't want to see those undermined.
I am sorry but I don't see how this is an argument. CDI has been out in the wild for quite some time now. Yet I still keep seeing people struggling with the basics of it. Enablement of alternatives included.
Log messages such as this one can be a quick guiding hand in finding why your app works, but not quite as you expected. A glance at basic log is a quick way of figuring out. It's also not as noisy since we are talking build time.
I think I've already quite clearly explained why log messages aren't the right way to do this. At development time I never see log messages. They're either completely hidden by gradle, or they're lost in a great spew of stuff in the console. Please don't try to convince me that you actually read the contents of the console when you run your test suite in IntelliJ because I know you don't.
So instead of making that great spew even worse, either solve the perceived problem (which I perceive to be a non-problem) properly or don't solve it at all.
None of our frameworks work by reporting developer errors in the log. There's a reason for that.
@mkouba
finally, we have a single "bean archive"
Wait, perhaps I misunderstood this comment.
Are you saying here that it's impossible to have beans defined in several different library jars at build time? I had understood from the ArC documentation that this was not the case, and that I can have @Alternative
s spread across several jars.
Anyway, I sure hope that's not the case. 馃槹
(On the other hand, it's the only way I can explain the fact that you think it's weird to have disabled @Alternative
beans at build time.)
Are you saying here that it's impossible to have beans defined in several different library jars at build time? I had understood from the ArC documentation that this was not the case, and that I can have @Alternatives spread across several jars.
You can have alternatives in as many archives (JARs) as you want. The point of Martin's comment is that in Quarkus you ultimately create one bean archive from all the jars and beans within them. With this in mind, you cannot have alternatives enabled on a per-bean-archive basis, which you can in standard CDI. Plus we only use beans.xml
as marker file anyway (not reading its contents), so you couldn't do "local" enablement there.
You can have alternatives in as many archives (JARs) as you want. The point of Martin's comment is that in Quarkus you ultimately create one bean archive from all the jars and beans within them.
Right, that's what I thought.
With this in mind, you cannot have alternatives enabled on a per-bean-archive basis, which you can in standard CDI.
Alright, so tell me what happens in each of the following situations:
My shiny new Quarkus program uses a CDI data access library, which has an injectable Connection
interface, and two implementations, SingleTenantConnection
and MultitenantConnection
, both marked @Alternative
, both disabled by default, since at the time the library is compiled, it has no clue whether it is running against a single-tenant or multitenant database.
In my Quarkus program which uses this library, I enable quarkus.arc.selected-alternatives=MultitenantConnection
because I have a multitenant database.
What happens?
Ooops, that didn't work! Well, so, the Quarkus environment is a bit different and I need to do something special, say, some sort of special transaction management. But I still want to reuse most of the implementation of MultitenantConnection
. So I create a QuarkusMultitenantConnection
bean that extend
s MultitenantConnection
and I don't mark it @Alternative
.
What happens?
Hrm, the plot thickens. It turns out that some of the deployments of my Quarkus program work against a single-tenant database, and some against a multitenant database. And that's determined by build-time configuration. So now I have two beans, QuarkusMultitenantConnection
and QuarkusSingleTenantConnection
, both marked @Alternative
, and at build time one of them is enabled via quarkus.arc.selected-alternatives=QuarkusMultitenantConnection
or whatever.
What happens?
Alright, so tell me what happens in each of the following situations:
Where are you trying to get with this? If we want to discuss how alternative selection works on Quarkus then maybe we should move it to separate thread. It's pretty far from the original point of the issue. All I was saying is that Quarkus doesn't do alternative enablement via beans.xml
. You can still use the property (quarkus.arc.selected-alternatives
); that's why we added it. And the way it works as it basically adds priority making it a global enablement across the deployment.
Your situations are pretty self-explanatory. Whatever you put in the property will a be selected alternative as if it had priority or was declared in beans.xml
. Second situation also behaves just like it would in classic CDI.
Where are you trying to get with this?
Does it print an INFO message because there are disabled @Alternative
beans?
If so, in which of the three situations?
All I was saying is that Quarkus doesn't do alternative enablement via
beans.xml
But it does the exactly equivalent thing using quarkus.arc.selected-alternatives
, unless I misunderstand, so I'm not sure why you keep repeating this as if it mattered. Surely I must be missing something.
What happens?
MultitenantConnection
is enabled for the whole app (i.e. every injection point with required type Connection
will receive the MultitenantConnection
bean). SingleTenantConnection
is ignored. The INFO is logged for the SingleTenantConnection
(and will be DEBUG after we "fix" this issue).
Ooops, that didn't work!
I don't understand what did not work?
What happens?
QuarkusMultitenantConnection
is used for any injection point with required type Connection
. SingleTenantConnection
and MultitenantConnection
are both ignored. The INFO is logged for both SingleTenantConnection
and MultitenantConnection
.
What happens?
QuarkusMultitenantConnection
is used everywhere. SingleTenantConnection
, MultitenantConnection
and QuarkusSingleTenantConnection
are ignored.
NOTE: The INFO log message is really useless and confusing for this kind of use case. However, this is not the only use case for @Alternative
and I'd even say that it's not even a typical use case (no matter what the original intent of CDI 1.0 was...).
All I was saying is that Quarkus doesn't do alternative enablement via beans.xml
But it does the exactly equivalent thing using quarkus.arc.selected-alternatives, unless I misunderstand, so I'm not sure why you > keep repeating this as if it mattered. Surely I must be missing something.
It's not an equivalent because quarkus.arc.selected-alternatives
selects an alternative per application/globally, i.e. any injection point will be satisfied with the same bean.
Whereas beans.xml
selection works locally/per bean archive, i.e. if there are the following classes:
interface Alpha {}
@Alternative
class Foo implements Alpha {}
@Alternative
class Bar implements Alpha {}
and bean archives: (1) dummy-1.jar
with beans.xml
which selects Foo
alternative and (2) dummy-2.jar
with beans.xml
which selects no alternative. Then, an Alpha
injection point inside dummy-1.jar
receives Foo
and an Alpha
injection point in dummy-2.jar
results in UnsatisfiedResolutionException
because there is no enabled bean that satisfies this IP.
(Not to mention that in regular CDI there are "inter-module injection" rules that come into play)
NOTE: The INFO log message is really useless and confusing for this kind of use case.
Well, exactly. And it's not even just one message in the examples I showed, it's multiple messages.
However, this is not the only use case for
@Alternative
No, surely not, but it is most certainly a legitimate use case for @Alternative
—indeed, it is the use case that @Alternative
was originally designed to address!
Now, if people use @Alternative
for other things, that's perfectly fine. I'm not proposing to go printing out naggy log messages in their use cases!
But _by the exact same token,_ it's not reasonable to get in the way of people who are using @Alternative
for the thing it was designed to do by nagging them as if they're doing something wrong.
I'd even say that it's not even a typical use case
Then if you think that, in the uses cases you care about, it's important to detect this situation and report it as a problem, it is on you to be able to distinguish the circumstances where there really is a problem, not just go out there with a big FU to me who is using @Alternative
for the precise thing it was designed for.
But the issue here is that you just haven't been creative about the problem at all. Instead of trying to properly identify the cases which are problematic, and come up with well-defined rules for reporting them via errors, you've just ratholed on the laziest possible solution which is to just stick in a System.out.println()
and then stop thinking about the problem!
It's not an equivalent because
quarkus.arc.selected-alternatives
selects an alternative per application/globally, i.e. any injection point will be satisfied with the same bean.
What?! This statement is completely wrong. @Alternative
enablement is an module-level thing in CDI, and is usually done in the beans.xml
file of the top-level archive, i.e. in the descriptor of the program that is depending on the other library bean archives. Off the top of my head I can't think of any case where it would make sense to do @Alternative
enablement it in the beans.xml
descriptor of the archive in which the bean is packaged!
Whereas
beans.xml
selection works locally/per bean archive
No, it doesn't. Read the spec. I wrote it, so i think I would remember something like that.
Well, wait, what I said isn't quite right. Sure, there is module-local enablement of @Alternative
s in CDI, because in Java EE you can have a multiple module deployment where different bean archives are different modules.
We don't have here, of course, there's just one module in Quarkus.
What I'm saying is that bean enablement _doesn't apply only to beans in the current archive_, it applies to beans in all the archives the current archive depends on. Which is the exact same situation you have with quarkus.arc.selected-alternatives
.
So OK, beans.xml
is "local" in the sense that it applies to injection points in the current archive, but it's non-local in the sense that the beans being enabled belong to any archive at all. (Which is the thing which actually matters in this discussion.)
There's no difference there. The only difference is you have what is conceptually a single-module deployment.
No, it doesn't. Read the spec. I wrote it, so i think I would remember something like that.
Yes, it does.
The spec defines bean archives just as an archive with some specific contents (be it beans.xml
or beans with bean defining annotations).
Moving on, we get to enabling alternatives for a bean archive which quotes:
An alternative may be explicitly declared using the
element of the beans.xml file of the bean archive. The element contains a list of bean classes and stereotypes. An alternative is selected for the bean archive if either:
This implies the behavior Martin described. It is how it's perceived and implemented as of today and has been as such for quite a few years without any change.
Obviously this is not the case for Quarkus where we simply have singular bean archive, hence quarkus.arc.selected-alternatives
works the same way as @Priority
and not like beans.xml
enablement.
Off the top of my head I can't think of any case where it would make sense to do @Alternative enablement it in the beans.xml descriptor of the archive in which the bean is packaged!.
First thing I can think of is a complex EE deployment where you may want to have a different bean handling certain behaviour (DB connection or whatnot) per archive and at the same time you don't want each of those beans to be visible to other archives. You can use alternatives enabled via beans.xml
for that. There is more cases, I am sure.
What I'm saying is that bean enablement doesn't apply only to beans in the current archive, it applies to beans in all the archives the current archive depends on.
There are two kinds of enablement defined in CDI. Global one is what you described, per-archive behaves like we described previously. In Quarkus, you only get to perform global enablement.
One of the reasons why we get to this is that not being able to perform per-archive enablement removes yet another use case where disabled alternative makes sense (as described in the third point of this comment)