Announcement Announcement Module
Collapse
No announcement yet.
How to configure session scoped beans? (Spring 2.0) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    <aop:scopedProxy>

    (Please ignore)

    Comment


    • #17
      I have a related question:
      http://forum.springframework.org/showthread.php?t=26609

      Thanks!

      Comment


      • #18
        Originally posted by Rick Evans
        Hi Rob



        You are mostly correct, in that XML bean definitions do now have an explicit 'scope' attribute, and that is enough to effect the scoping of beans at the required scope (singleton, prototype, request, session, globalSession, <insert custom scope here>).

        Consider the following bean definition:

        Code:
        <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
        This bean definition is scoped at the HTTP Session level; that is to say that an instance of the UserPreferences class with the supplied configuration (not a whole lot in this case) would be associated with the lifecycle of each distinct HTTP Session. When the HTTP Session is disposed, the attendant UserPreferences object would be removed from said Session and go out of scope and be similarly disposed of (providing nothing else was holding a reference to it).

        If you have a reference to the Spring IoC container, you can can call 'getBean("userPreferences")' on it and if you are in HTTP Session A you will get the exact same UserPreferences object back no matter how many times you call 'getBean("userPreferences")' so long as HTTP Session A is still active. If HTTP Session A is deactivated, expires, or you call 'getBean("userPreferences")' in the scope of another HTTP Session (let's call it B), then you will get another, different UserPreferences object back.

        And now onto answering your question

        The reason why '<aop:scoped-proxy/>' is required is best explained by picking apart the following bean definition (please note that the 'userPreferences' bean definition as it stands is incomplete):

        Code:
        <!-- same bean definition as before -->
        <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
        
        <bean id="userManager" class="com.foo.UserManager">
            <property name="userPreferences" ref="userPreferences"/>
        </bean>
        From the above configuration it is evident to see that the singleton bean 'userManager' is being injected with a reference to the HTTP Session-scoped bean 'userPreferences'. The salient point here is that the 'userManager' bean is a singleton... it will be instantiated exactly once per container, and it's dependencies (in this case only one, the 'userPreferences' bean) will also only be injected once. This means that the 'userManager' will (conceptually) only ever operate on the exact same 'userPreferences' object, i.e. the one that it was originally injected with. This is not what one wants when one is injecting a HTTP Session-scoped bean as a dependency into a collabroating object. What we do want is a single 'userManager' object, and then, for the lifetime of a HTTP Session, we want to see and use a 'userPreferences' object that is specific to said HTTP Session.

        Rather what we need then is to inject some sort of object that exposes the exact same public interface as the 'UserPreferences' class (ideally an object that 'isa' 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', which will be blissfully unaware that the UserPreferences reference that it is holding onto is a proxy. In the cas eof this example, when a UserManager instance invokes a method on the dependency-injected UserPreferences, 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.

        That is why you need the following, correct and complete, configuration when injecting request-, session-, and globalSession-scoped beans into collaborating objects:

        Code:
        <!-- same bean definition as before -->
        <bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
            <aop:scoped-proxy/>
        </bean>
        
        <bean id="userManager" class="com.foo.UserManager">
            <property name="userPreferences" ref="userPreferences"/>
        </bean>
        I hope this helps explain Spring's scoping support. If not, please do ping back this thread so that I can go off, have a think, and then update the Spring reference documentation to be clearer in this regard.

        Cheers
        Rick
        I cannot work with sessions. In this example, I think "userManager" is create just one time, and "userPreferences" is diferent for each HTTP Session. But here it creates "userPreferences" just on time too. Im using RC2.

        Where is my wrong?

        Adilson

        Comment


        • #19
          Originally posted by Rick Evans
          Hi Rob

          ......

          You are mostly correct, in that XML bean definitions do now have an explicit 'scope' attribute, and that is enough to effect the scoping of beans at the required scope (singleton, prototype, request, session, globalSession, <insert custom scope here>).Cheers
          Rick
          It appears that there is a bug in this code somewhere, or perhaps a subtlety that I am missing.
          I can make these sort of examples work for many combinations of session bean , controller and singleton. However one in particular always causes the factory to spit a: java.lang.IllegalStateException:
          "Scope 'request' is not active; nested exception is java.lang.IllegalStateException: No thread-bound request: use RequestContextFilter"

          The bean itself does not appear to be a problem if I add it to the a controller as a (made up for testing) Object property. But I cannot add it as a property of the same type as the bean.

          I would love to pass on the code, but I cannot make it publicly available. (dammit)

          So I guess this is just a note to those on the forums I have seen who do not seem to be able to make this work because of exceptions.

          A) The error is full of nonsense
          b) It is caused by an as yet unknown combination of request/session scoped beans and possibly controllers.

          If I find out what it is, I will let you all know - I am too busy to bother at the moment.

          UPDATE:
          Looked even closer and it still makes no sense. The bean is not being treated any differently to any other.
          Remember: if I create a property "Object o" and add the bean as a ref, there is no problem.

          I am out of ideas...

          Here is the top of the stack trace:
          Caused by:
          java.lang.IllegalStateException: No thread-bound request: use RequestContextFilter
          at org.springframework.web.context.scope.RequestConte xtHolder.currentRequestAttributes(RequestContextHo lder.java:60)
          at org.springframework.web.context.scope.AbstractRequ estAttributesScope.get(AbstractRequestAttributesSc ope.java:40)
          at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:274)
          at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:153)
          at org.springframework.aop.target.AbstractPrototypeBa sedTargetSource.newPrototypeInstance(AbstractProto typeBasedTargetSource.java:58)
          at org.springframework.aop.target.PrototypeTargetSour ce.getTarget(PrototypeTargetSource.java:30)
          at org.springframework.aop.framework.Cglib2AopProxy$D ynamicAdvisedInterceptor.getTarget(Cglib2AopProxy. java:673)
          at org.springframework.aop.framework.Cglib2AopProxy$D ynamicAdvisedInterceptor.intercept(Cglib2AopProxy. java:624)
          at com.***.***.**.****$$EnhancerByCGLIB$$c6c7d446.siz e(<generated>)
          Last edited by mrshanepaul; Jul 18th, 2006, 08:43 PM.

          Comment


          • #20
            Hi

            Originally posted by adilsonv
            I cannot work with sessions. In this example, I think "userManager" is created just one time, and "userPreferences" is different for each HTTP Session. But here it creates "userPreferences" just one time too. I'm using RC2.

            Where is my wrong?
            Adilson
            As I see it you aren't going wrong. I will shortly be committing one of these so-called 'showcase' sample applications that just demonstrates the web scoping and nothing else; it will at the very least give you a fully working application to look at and play with. Expect it in time for 2.0 final (just a week or so away now).

            Originally posted by mrshanepaul
            It appears that there is a bug in this code somewhere, or perhaps a subtlety that I am missing.
            I can make these sort of examples work for many combinations of session bean , controller and singleton. However one in particular always causes the factory to spit a: java.lang.IllegalStateException:
            "Scope 'request' is not active; nested exception is java.lang.IllegalStateException: No thread-bound request: use RequestContextFilter"

            The bean itself does not appear to be a problem if I add it to the a controller as a (made up for testing) Object property. But I cannot add it as a property of the same type as the bean.

            I would love to pass on the code, but I cannot make it publicly available. (dammit)

            So I guess this is just a note to those on the forums I have seen who do not seem to be able to make this work because of exceptions.

            A) The error is full of nonsense
            b) It is caused by an as yet unknown combination of request/session scoped beans and possibly controllers.
            Shucks In my (admittedly constrained) sample application I can inject a session-scoped bean with no problems; I can then spawn multiple Http Sessions and watch the logging output in the Tomcat console window showing me that a new bean is being created for every new Http Session. It's hard to diagnose what is going on in your case without some more to go on. If you like you can email me directly ([email protected]) with the relevant portions of your code in strictest confidence, etc.

            Sorry I can't be more helpful right now guys, cheers
            Rick

            Comment


            • #21
              Originally posted by Rick Evans
              Shucks In my (admittedly constrained) sample application I can inject a session-scoped bean with no problems; I can then spawn multiple Http Sessions and watch the logging output in the Tomcat console window showing me that a new bean is being created for every new Http Session. It's hard to diagnose what is going on in your case without some more to go on. If you like you can email me directly ([email protected]) with the relevant portions of your code in strictest confidence, etc.

              Rick
              We have worked around the solution, of course, but thought that it might still be an interesting debugging situation. I have sent the details by email.

              My current thought is that the AOP proxy is spitting the dummy over my interfaces and the way I am handling the bean. Poor AOP proxy...

              PS: Please note that it worked for everything else, so I am not complaining! I have been waiting for this for some time.

              Comment


              • #22
                I am having the same problem as noted in this thread and have taken steps to try and get this to work. I get the following error:

                javax.ejb.CreateException: PatientStateManagerBean create failed: java.l
                ang.IllegalStateException: No Scope registered for scope 'session'
                gov.va.med.datasharing.th.comm.DestinationExceptio n: PSMSender failed to send: j
                ava.rmi.RemoteException: Error in ejbCreate:; nested exception is:
                javax.ejb.CreateException: PatientStateManagerBean create failed: java.l
                ang.IllegalStateException: No Scope registered for scope 'session'
                at gov.va.med.datasharing.th.ejb.PSMSendSender.send(P SMSendSender.java:6

                I have done everything in this email except adding this listener. When I add it, a ClassNotFoundException occurs. This is not in the release; which is 2.0 RC3. I am not using the Spring web framework.

                <listener>
                <listener-class>org.springframework.web.context.scope.Reques tContextListener</listener-class>
                </listener>

                Also I've had prolems with the <aop:scoped-proxy/> tag. This SAXException is thrown;

                Caused by:
                org.springframework.beans.factory.BeanDefinitionSt oreException: Line 70 in XML d
                ocument from class path resource [thconfig/chdr-th-process-spr-conf.xml] is inva
                lid; nested exception is org.xml.sax.SAXParseException: cvc-complex-type.2.4.c:
                The matching wildcard is strict, but no declaration can be found for element 'ao
                p:scoped-proxy'.
                Caused by:
                org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is
                strict, but no declaration can be found for element 'aop:scoped-proxy'.
                at org.apache.xerces.util.ErrorHandlerWrapper.createS AXParseException(Un
                known Source)
                at org.apache.xerces.util.ErrorHandlerWrapper.error(U nknown Source)
                at org.apache.xerces.impl.XMLErrorReporter.reportErro r(Unknown Source)
                at org.apache.xerces.impl.XMLErrorReporter.reportErro r(Unknown Source)
                at org.apache.xerces.impl.xs.XMLSchemaValidator$XSIEr rorReporter.reportE
                rror(Unknown Source)


                Does this require a specific version of xerces to run?

                Comment

                Working...
                X