quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.54k stars 2.61k forks source link

Qute: access to beans without name in qute templates #41932

Open maxandersen opened 1 month ago

maxandersen commented 1 month ago

Description

when using qute web templates or even plain qute templates default beans without a name is not accessible.

i.e. in java code I can do @Inject UserInfo user; but not possible in Qute.

You can do tricks like:

@TemplateExtension
public class Globals {
    public static UserInfo user() {
        return Arc.container().instance(UserInfo.class);
    }
}

but after zulip discussion: https://quarkusio.zulipchat.com/#narrow/stream/187038-dev/topic/qute.20web.20.2F.20how.20to.20.40named.20default.20beans.3F/near/451771103 suggestion on supporting things like the following:

{@io.quarkus.oidc.UserInfo user}

if user not available as parameter inject it.

OR explicit inject in header

{@inject io.quarkus.oidc.UserInfo user}

OR enhance {cdi:} to support

{cdi:UserInfo.name}

to look at build time provided names/types.

Implementation ideas

No response

quarkus-bot[bot] commented 1 month ago

You added a link to a Zulip discussion, please make sure the description of the issue is comprehensive and doesn't require accessing Zulip

This message is automatically generated by a bot.

quarkus-bot[bot] commented 1 month ago

/cc @mkouba (qute)

mkouba commented 1 month ago

So if I understand it correctly it's not about access to named beans but about access to beans with no name. I will change the title of the issue. Feel free to update the title if needed.

FroMage commented 1 month ago

I dislike the {@io.quarkus.oidc.UserInfo user} and {@inject io.quarkus.oidc.UserInfo user} syntax because unless you're going to re-use that bean, making a variable for it is a lot of ceremony, especially if you need to go up to the start of the template to add it there and come back.

I propose to expand the cdi: namespace resolver so that the following work:

mkouba commented 1 month ago
  • {cdi:io.quarkus.oidc.UserInfo} if there is a matching FQN bean of that type

:-1: I think that it's a misuse of the syntax. Qute ref guide is pretty clear that the dot notation is used to access properties or call (virtual) methods.

Also it would not work for parameterized types; e.g. if there's a bean with type List<String>.

If we want to support unnamed beans in templates it should be clear that we're doing a type lookup, e.g. something like {cdi:byType('UserInfo')} and {cdi:byType('io.quarkus.oidc.UserInfo')} (byType | lookup | find | ...). I know it's more typing and not very nice but the proposal above IMO hides too much and we will have to cover a lot of edge cases. For example, detect a failure when there's a bean with name UserInfo and type UserInfo.

FroMage commented 1 month ago

Qute ref guide is pretty clear that the dot notation is used to access properties or call (virtual) methods.

That documentation can be updated :)

Also it would not work for parameterized types; e.g. if there's a bean with type List.

We could argue that those require the longer alternative {cdi:'org.foo.Bar<Gee>'}.

If we want to support unnamed beans in templates it should be clear that we're doing a type lookup, e.g. something like {cdi:byType('UserInfo')} and {cdi:byType('io.quarkus.oidc.UserInfo')} (byType | lookup | find | ...). I know it's more typing and not very nice

I could get behind {cdi-type:UserInfo} I think that'd be fine.

For example, detect a failure when there's a bean with name UserInfo and type UserInfo

That's easy, the resolution rules are: @Named first, then unqualified type if unambiguous, then FQN. Simple rules.

ia3andy commented 1 month ago

If we want to support unnamed beans in templates it should be clear that we're doing a type lookup, e.g. something like {cdi:byType('UserInfo')} and {cdi:byType('io.quarkus.oidc.UserInfo')} (byType | lookup | find | ...). I know it's more typing and not very nice but the proposal above IMO hides too much and we will have to cover a lot of edge cases. For example, detect a failure when there's a bean with name UserInfo and type UserInfo.

I like this solution where when you want something not named, you lookup. The others seem more hacky and confusing (having yet another namespace).