Announcement Announcement Module
Collapse
No announcement yet.
A couple of problems with session scope beans Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • A couple of problems with session scope beans

    Hi, folks,

    a couple of questions from a Spring MVC newbie...

    First, I have a problem trying to inject a session scope bean into a controller.

    Here's the bean config:

    Code:
    <bean id="userSessionContainer" class="UserSessionContainerImpl" scope="session">
            <aop:scoped-proxy />
    </bean>
    
    <bean id="loginController" class="com.condosmart.web.controller.LoginController">
    ...
            <property name="userSessionContainer" ref="userSessionContainer" />
    ...
    </bean>
    Controller class:

    Code:
    private UserSessionContainer userSessionContainer;
    
    public void setUserSessionContainer(UserSessionContainer userSessionContainer) {
        this.userSessionContainer = userSessionContainer;
    }
    
    protected ModelAndView onSubmit(Object command, BindException errors) throws Exception {
    //... (userByLogin is loaded here)
    userSessionContainer.setPrincipal(userByLogin);
    //...
    }
    And now I want to display, say, the name of the Principal in a jsp:

    Code:
    ${userSessionContainer.principal.name}
    and nothing is displayed!

    If instead of using the <aop:scoped-proxy> i+ setter injection I just get the bean from the Application Context:

    Code:
    UserSessionContainer userSessionContainer =
    (UserSessionContainer)getApplicationContext().getBean(Constants.USER_SESSION_CONTAINER_BEAN_ID);
    
    userSessionContainer.setPrincipal(userByLogin);
    everything works fine.

    Actually, I have also noticed that when I try to access any session-scoped bean from a jsp using JSTL:
    Code:
    ${sessionBean.blah}
    I don't get anything. And as soon as I get this bean somewhere in a controller
    Code:
    applicaitonContext.getBean("sesionBeanId")
    JSTL tags do get it.

    I am definitely missing something here... any advice is greatly appreciated.

    Yours sincerely,
    Andrey.
    Last edited by ashulinsky; Apr 18th, 2007, 10:13 AM.

  • #2
    No object is referred if nothing is displayed in a JSP file. You need to give your object a name in your controller and refer it in your JSP file. You can study more those samples in the distributed package to understand how to get it work.

    HTH.

    Comment


    • #3
      Thanks for the prompt reply

      Originally posted by vw729 View Post
      No object is referred if nothing is displayed in a JSP file. You need to give your object a name in your controller and refer it in your JSP file. You can study more those samples in the distributed package to understand how to get it work.
      Right, the session object is not even initialized until I explicitly do applicationContext.getBean(...).

      However, the question is - why isn't it? Is it the way it's supposed to work? I thought that any session object would be created and put to any new session automatically. I have also tries setting lazy-init="false" to no result.

      In regards to the setting injection of a session bean to a singleton controller through <aop:scoped-proxy> - in this case a proxy is created, I can work with it within the controller but - again - don't have it in a jsp. Once again, the real session object doesn't seem to be created - and I thought it would after reading this part of the reference:

      http://static.springframework.org/sp...scopes-session

      Rather what you need then is to inject some sort of object that exposes the exact same public interface as the UserPreferences class (ideally an object that is a UserPreferences instance) and that is smart enough to be able to go off and fetch the real UserPreferences object from whatever underlying scoping mechanism we have chosen (HTTP request, Session, etc.). We can then safely inject this proxy object into the 'userManager' bean, which will be blissfully unaware that the UserPreferences reference that it is holding onto is a proxy. In the case of this example, when a UserManager instance invokes a method on the dependency-injected UserPreferences object, it is really invoking a method on the proxy... the proxy will then go off and fetch the real UserPreferences object from (in this case) the HTTP Session, and delegate the method invocation onto the retrieved real UserPreferences object.

      So, where is the catch?

      Yours sincerely,
      Andrey.

      Comment


      • #4
        <<property name="userSessionContainer" ref="userSessionContainer" />

        You have double "<" in your config.

        Comment


        • #5
          Originally posted by mwang2008 View Post
          <<property name="userSessionContainer" ref="userSessionContainer" />

          You have double "<" in your config.
          Sorry, it's a copy-paste problem, the real config is fine.

          Comment


          • #6
            It's instantiated as soon as it is needed. If you have your controller set up as singleton with a dependency on the session-scope proxy the proxy gets injected on initialization of the controller. You should be able to debug that one or log it in the setUserSessionContainer(..). The actual session-scoped object gets instantiated on the first access to the proxy. This should be your userSessionContainer.setPrincipal(userByLogin). I can't see something wrong in your code, so you probably need to debug or log if those both methods are called.

            Jörg

            Comment


            • #7
              Jorg,

              thanks, sounds like session-scope beans are always "lazy-initialized" and there's no way to instantiate them automatically on a session's creation. If so, it means that a session-scope bean can not be used in a jsp until the bean is referenced (and as a result instantiated) somewhere in the code. Right?

              Regarding the injection - I did some debugging and the userSessionContainer.setPrincipal(userByLogin) method was successfully executed. The userSessionContainer.getPrincipal() invocation did return the user set by the setter. Still, it seems all this happened to the proxy, the real object had not been instantiated - neither its constructor nor the setter were called. And - again - no reference in the jsp...

              Yours sincerely,
              Andrey.

              Comment


              • #8
                Originally posted by ashulinsky View Post
                sounds like session-scope beans are always "lazy-initialized" and there's no way to instantiate them automatically on a session's creation.
                That's correct.

                Originally posted by ashulinsky View Post
                If so, it means that a session-scope bean can not be used in a jsp until the bean is referenced (and as a result instantiated) somewhere in the code.
                It depends on how you access them. I'd completely refrain from accessing those beans directly from the session. It's somehow a Spring internal how it stores the beans in the session and you are relying on it (though using most simple approach with bean name = session attribute name IIRC). I have an application based on Spring MVC and use session-scoped beans as well. I always inject them explicitly into the JSP via the ModelAndView. So you also can be sure that the object is initialized.

                Originally posted by ashulinsky View Post
                The userSessionContainer.getPrincipal() invocation did return the user set by the setter. Still, it seems all this happened to the proxy, the real object had not been instantiated - neither its constructor nor the setter were called. And - again - no reference in the jsp...
                Hmm, that's not possible. The call to the setter or the getter must "end" somewhere. And it can't be the proxy as it only delegates the calls. I fear something in your setup must still be wrong. As soon as a method is called on the proxy the session-scope bean must be instantiated and the method call is delegated to it.

                To understand more of the details and maybe find the reason for your problem you might have a look into the ScopedProxyFactoryBean, the DefaultScopedObject and the SessionScope.

                Jörg

                Comment


                • #9
                  Jorg,

                  thanks a lot for your help. You were right about the session bean instantiation through a proxy. It works fine, I was doing wrong tests. And it is stored in the session as an attribute with the name 'scopedTarget.beanName' so I can actually access it.

                  About the rationale for using a session bean - basically, I want to have an object that is available to most of the controllers controllers and holds some data that should be displayed on all jsps - I don't want to inject it to every model. So, a session-scoped bean seemed like a natural choice.
                  You have a valid point - I do use some Spring internal convention that way, but what are the other options?

                  I thought about having a session-scoped command that holds the data - but I can't easily access it from all the controllers.

                  Another alternative would be to explicitly set/get this bean to sessions using some property name. I don't like it as Spring does such a wonderful job separating the controller code from the Http stuff and I don't want to break the pattern... can't really think of anything else :-)

                  Yours sincerely,
                  Andrey

                  Comment


                  • #10
                    Originally posted by ashulinsky View Post
                    About the rationale for using a session bean - basically, I want to have an object that is available to most of the controllers and holds some data that should be displayed on all jsps - I don't want to inject it to every model. So, a session-scoped bean seemed like a natural choice.
                    I have done something very similar for similar requirements. I only inject it explicitly.

                    Originally posted by ashulinsky View Post
                    You have a valid point - I do use some Spring internal convention that way, but what are the other options?
                    From the options mentioned your current approach is the cleanest and best one available IMO. It's not more likely to break than any "put this object into session from hand". You don't have to care how the object gets into the session in your controllers and if it is changed, it breaks all your pages, not only one by one when you change the session attribute name yourself, so it's more likely to notice it at least.

                    Jörg

                    Comment


                    • #11
                      Finally got it to work

                      Read lots of form posts on this issue.
                      Turns out I had the config correct, but when inserting my session scoped proxy into the singleton I logged the insert via log4j. But what that actually did was trying to create the actual session scoped bean, resulting in a session not bound exception during startup of the application. So to anybody out there who is pulling out their hair right now.. Make sure you do not call any methods on the proxy before you are actually in a session!!!!

                      Regards and hope this helps!

                      Comment

                      Working...
                      X