4 Replies Latest reply on Apr 23, 2014 4:16 AM by simon.kulessa

    Injection of non-proxy objects

    simon.kulessa

      I having an 'rare' issue with Weld 2.1.2.Final were an injected object is not a proxy object.

      As far as I unterstand the spec states that 'normal scoped' dependencies must be inject via proxy.

       

      I have a class like this, where the injected classes B and C are ApplicationScoped as well.

       

      @ApplicationScoped

      class A {

       

        @Inject

        B b;

       

        @Inject

        C c;

       

        @PostConstruct

        void init() {

          System.out.println(b.getClass().getName());

          System.out.println(c.getClass().getName());

        }

      }

       

      In my case the PostConstruct Method of C was called before the sysouts in the init() method of class A are executed.

      What I see now is that the injected object for B is a proxy object, while the injected object for C is not a proxy object.

       

      Can someone confirm this issue?

        • 1. Re: Injection of non-proxy objects
          tremes

          Hi Simon.

          This sounds weird. Which container do you  use? How does class B and C exactly look like? When do you exactly observe this state? I guess you call class A from your application.

          • 2. Re: Injection of non-proxy objects
            simon.kulessa

            Hi Tomas,

             

            as container we are using Tomcat.

            Class B and C look similiar to Class A. Basically these classes form some kind of dependency hierarchy that is updated (in this case) after login.

            At this time some bean calls a utility method which injects the starting point of this hierarchy (neither A,B or C) and then updates the dependencies.

            In the end this method returns a list which should contain each dependency only once.

             

            In the scenario described above, these classes do not exist yet and will be created.

            The result was certain items were contained multiple in the list. While debuging I figured out that some of these classes are proxy object while others are not.

            I ended up in the post construct method of class A, were I found that a non proxy object is injected.

             

            Maybe you know which class actually handels the injection or creation of the proxy object. I might be able to get some more information when I debug this code.

            • 3. Re: Re: Injection of non-proxy objects
              tremes

              Hi!

              I am not 100% sure that I understand your scenario, but I guess you have circular dependencies between A, B and C classes (assuming B is injecting C, A and so on). In this case the container is not required to create client proxies everytime. In the CDI spec there is:

              5.4. Client proxies

              .....

              The container may use a client proxy when creating beans with circular dependencies.

              This is only necessary when the circular dependencies are initialized via a managed bean

              constructor or producer method parameter. (Beans with scope @Dependent never have circular

              dependencies.)

               

              and:

              6.1.1. The CreationalContext interface

              .....

              The implementation of Contextual is not required to call push(). However, for certain bean

              scopes, invocation of push() between instantiation and injection helps the container minimize the

              use of client proxy objects (which would otherwise be required to allow circular dependencies).

               

              • 4. Re: Injection of non-proxy objects
                simon.kulessa

                Hi,

                 

                thanks for the answer. Circular dependencies certainly exist somewhere between these classes.

                 

                I had a different interpretation of the spec at point 5.4.

                An injected reference, or reference obtained by programmatic lookup, is usually a contextual reference as defined by [contextual_reference].

                 

                A contextual reference to a bean with a normal scope, as defined in [normal_scope], is not a direct reference to a contextual instance of the bean

                (the object returned by Contextual.create()). Instead, the contextual reference is a client proxy object. ....

                 

                There are a number of reasons for this indirection:

                ....

                I first states (okay, I ignored the usually in the first sentence ) it is not a direct reference, then some reasons follow why that might be the case.

                That the reason itself might define a different behaviour is something I missed.

                 

                Additionaly regarding the last part of point 5.4

                Client proxies may be shared between multiple injection points. For example, a particular container might instantiate exactly one client proxy object per bean. (However, this strategy is not required by this specification.)

                I guess this means even so a bean is ApplicationScoped multiple proxy objects might exist.