Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.2.0
    • Fix Version/s: 2.2.0
    • Component/s: None
    • Labels:
      None

      Description

      org.jvnet.hk2.guice.bridge.internal.GuiceServiceHk2Bean assumes a name descriptor will always be null which will later prevent HK2 from doing a named injection.

        Activity

        Hide
        awawaw added a comment - - edited

        Ah, yes sorry I can see how there's confusion there. In my own test case, I'm calling "Service" a guice injected service, whereas the HK2 service is a "Resource".

        I think if we can base off of "theyelllowdart"'s comment above's test code, we just need to add this to GuiceBridgeModule:
        bind(GuiceService1.class).annotatedWith(Names.named("named").to(GuiceService1Impl.class);

        Then, in HK2ServiceNamedInjection, just add a constructor like:

        @Inject
        public HK2ServiceNamedInjection(GuiceService1 guiceService1) {

        This code should fail as there is no unnamed class/instance of GuiceService1 that's bound. In other words, using only Guice, if we tried to do injector.getInstance(GuiceService1.class), it would throw an exception.

        Show
        awawaw added a comment - - edited Ah, yes sorry I can see how there's confusion there. In my own test case, I'm calling "Service" a guice injected service, whereas the HK2 service is a "Resource". I think if we can base off of "theyelllowdart"'s comment above's test code, we just need to add this to GuiceBridgeModule: bind(GuiceService1.class).annotatedWith(Names.named("named").to(GuiceService1Impl.class); Then, in HK2ServiceNamedInjection, just add a constructor like: @Inject public HK2ServiceNamedInjection(GuiceService1 guiceService1) { This code should fail as there is no unnamed class/instance of GuiceService1 that's bound. In other words, using only Guice, if we tried to do injector.getInstance(GuiceService1.class), it would throw an exception.
        Hide
        jwells added a comment -

        Oh wait a second. Are you saying that you are expecting GuiceService1 to not work because there is no un-named Service? So, hk2 has something for that:

        https://hk2.java.net/2.5.0-b24/apidocs/org/glassfish/hk2/api/Unqualified.html

        The way this is interpreted is that qualifiers define required things which must be on the services. Hence even though GuiceService1 has a name on it, the injection point does not have any requirements and so injecting the service with the name bound on it is what hk2 does.

        If that is NOT the behavior, use @Unqualified which will force the injection point to only bind a service with NO qualifiers. (You can also pick specific qualifiers to NOT bind with @Unqualified as well, but in this case it looks like you can just use the default version of @Unqualified).

        So if you change your case to be:

        @Inject
        public HK2ServiceNamedInjection(@Unqualified GuiceService1 guiceService1)

        then it should work for you

        Show
        jwells added a comment - Oh wait a second. Are you saying that you are expecting GuiceService1 to not work because there is no un-named Service? So, hk2 has something for that: https://hk2.java.net/2.5.0-b24/apidocs/org/glassfish/hk2/api/Unqualified.html The way this is interpreted is that qualifiers define required things which must be on the services. Hence even though GuiceService1 has a name on it, the injection point does not have any requirements and so injecting the service with the name bound on it is what hk2 does. If that is NOT the behavior, use @Unqualified which will force the injection point to only bind a service with NO qualifiers. (You can also pick specific qualifiers to NOT bind with @Unqualified as well, but in this case it looks like you can just use the default version of @Unqualified). So if you change your case to be: @Inject public HK2ServiceNamedInjection(@Unqualified GuiceService1 guiceService1) then it should work for you
        Hide
        awawaw added a comment -

        Okay, that's a bit weird though. If say you have two different named bindings for a class, and no unnamed binding. Then, which class would it be reasonable to use when injecting? Doesn't this lead to unpredictable/surprising behavior?

        I guess the use case here is integrating with an existing application, which already has all of Guice setup. If I forget to add "@Named("foo")" to new code which has injection, then I would expect an error, otherwise it would possibly lead to non-deterministic behavior at runtime.

        Show
        awawaw added a comment - Okay, that's a bit weird though. If say you have two different named bindings for a class, and no unnamed binding. Then, which class would it be reasonable to use when injecting? Doesn't this lead to unpredictable/surprising behavior? I guess the use case here is integrating with an existing application, which already has all of Guice setup. If I forget to add "@Named("foo")" to new code which has injection, then I would expect an error, otherwise it would possibly lead to non-deterministic behavior at runtime.
        Hide
        jwells added a comment -

        It is never non-deterministic, it will follow the rules for choosing that hk2 uses for any injection point with multiple possible services to inject which are basically that it'll choose:

        1. The service with the highest ServiceLocator id (so services in children get picked before services in parents)
        2. If #1 is a tie then amongst the services with the higest ServiceLocator ID the service with the lowest Service ID (so "older" descriptors will get chosen over newer ones)

        Show
        jwells added a comment - It is never non-deterministic, it will follow the rules for choosing that hk2 uses for any injection point with multiple possible services to inject which are basically that it'll choose: 1. The service with the highest ServiceLocator id (so services in children get picked before services in parents) 2. If #1 is a tie then amongst the services with the higest ServiceLocator ID the service with the lowest Service ID (so "older" descriptors will get chosen over newer ones)
        Hide
        jwells added a comment -

        Looks like it works as expected with perhaps the use of @Unqualified

        Show
        jwells added a comment - Looks like it works as expected with perhaps the use of @Unqualified

          People

          • Assignee:
            jwells
            Reporter:
            theyelllowdart
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: