2 Replies Latest reply on Mar 28, 2012 6:03 PM by christopherp

    Understanding @Inject vs @Inject Instance<> and .get()

    christopherp

      I'm a little confused about which to use in the following situation:

       

      Suppose the servlet creates an Application that handles the user's http session, and the application is similar to this:

       

          public class Application extends AbstractHTTPApplication {

         

          @Inject

          private Instance<MainView> mainView;

       

          public void setupApplication() {

             this.setView( mainView.get() );

           }

       

      Later on I have a `@SessionScoped` bean `SSB` that I want to inject into each user's bean:

       

          @SessionScoped

          public class SSB {}

       

      Now, when I tried a regular `@Inject SSB ssb;` as a field in `A`, I do not get a new `SSB` for each user:

       

           public class MainView {

       

               @Inject

               private SSB usersSSB;

       

               public someMethod() {

                    usersSSB.doSomething();

                    System.identityHashCode( usersSSB );

                }

            }

       

      Testing with two users, I get the *same* instance of usersSSB in both user's sessions.  I didn't think this was possible... I thought, since SSB is SessionScoped, a new one will be given to each user session, and no matter where it is @Inject ed it will refer to *that* user's `SSB`.

       

      So, instead, I tried:

       

          public class MainView {

       

             @Inject

             private Instance<SSB> usersSSB;

       

             public someMethod() {

                   usersSSB.get().doSomething();

                   System.identityHashCode( usersSSB.get() );

              }

          }

       

       

      Now it reports a different `usersSSB` for each user, finally.

       

      What's happening here? When I call `usersSSB.get()` later on in each user's session, will the `usersSSB.get()` return *that same bean* for *that same* user each time?

       

      If it helps, I'm running on Glassfish 3.1.2.  Thanks for any help on this. I just want to be sure when I inject a SessionScoped bean, I will be getting the exact same bean for that user, always, until their session ends.  Maybe I should use a different approach?

        • 1. Re: Understanding @Inject vs @Inject Instance<> and .get()
          luksa

          You have only one instance of MainView, so its field usersSSB can only point to one instance of SSB.

           

          Of course, if the field is an Instance<SSB>, it also points to only one instance of Instance<SSB>. However, calling .get() on it can return different instances of SSB, depending on the scope - that's why you get different SSBs for each user/session.

          • 2. Re: Understanding @Inject vs @Inject Instance<> and .get()
            christopherp

            Hi Marko, thanks for the reply!  I'm honestly having trouble wrapping my head around this. There is a new MainView created for each application, and each application is a SessionScoped bean created by the servlet.  Here's some more code that might explain what's happening (I apologize for the cross-posting from SO, I just wanted to see if a weld expert might be able to figure this out too):

             

            The Application class is being injected into the Servlet on a new HttpServletRequest:

            public abstract class AbstractCdiApplicationServlet extends
               
            AbstractApplicationServlet {
            @Inject
            protected Instance<ApplicationWrapper> wrapper;

            @Override
            protected Application getNewApplication(HttpServletRequest request)
                   
            throws ServletException {
               
            return wrapper.get().getApplication();
            }
            ...etc etc

            And the ApplicationWrapper is a SessionScoped bean:

            @SuppressWarnings("serial")
            @SessionScoped
            public class ApplicationWrapper implements Serializable {
            @Inject
            private AbstractCdiApplication application;

            public AbstractCdiApplication getApplication() {
               
            return application;
            }
            }

            Doesn't this mean that calling @Inject SSB usersSSB anywhere in MainView (or any object within that user's session) should give me that user's session-scoped bean, and always that same session-scoped bean, for each user's session? Meaning -- different usersSSB for different users, because each user has a different session.

            After all, the Application itself is a SessionScoped bean, injected into and attached to the user's HTTP Session by the getNewApplication method of the servlet? I mean, it is the Application object that injects and attaches the MainView class, after all, right? So that means MainView is a session-scoped bean, doesn't it?

            I'm just trying to figure out how this all works, I guess. Thanks for the help!