Spring beans, like the ones from JavaBeans, use the scopes. We've already seen two of them, singleton and prototype. It's the right time to discover 3 new scopes.
Data Engineering Design Patterns

Looking for a book that defines and solves most common data engineering problems? I wrote
one on that topic! You can read it online
on the O'Reilly platform,
or get a print copy on Amazon.
I also help solve your data engineering problems 👉 contact@waitingforcode.com 📩
This article will be divided in 2 parts. Each part will describe a new bean scope. So, in the first one, we'll discover the request scope. The second described scope will be session and global session scope. All parts will be composed by a theoretical introduction and real life use. These new concepts are only valid in web-aware Spring's application context.
What is request scope in Spring ?
Bean annotated with this scope is initialized at every request. It sounds like a description of prototype scope but they are some differences. The first difference is that prototype scope is available globally in Spring's context. The request one is only available for web applications. The second one is that prototype beans are initialized at demand whereas request beans are constructed at every request, event without explicit desire of programmer. In plus, they are one and exactly one instance of request scoped bean. In the other side, you can have one or more instance of prototype scoped bean.
In the following code you can see the example of request scope bean:
<bean id="shoppingCartRequest" class="com.waitingforcode.scope.ShoppingCartRequest" scope="request"> <aop:scoped-proxy/> </bean>
// request bean // injection sample @Controller public class TestController { @Autowired private ShoppingCartRequest shoppingCartRequest; @RequestMapping(value = "/test", method = RequestMethod.GET) public String test(HttpServletRequest request) { LOGGER.debug("shoppingCartRequest is :"+shoppingCartRequest); // ... } }
Please note the presence of <aop:scoped-proxy /> tag. It means the use of proxy objects. So in reality, TestControllers holds a reference to proxy object. This object forwards after all calls to the real ShoppingCartRequest object.
Sometimes we need to use another servlet that DispatcherServlet to treat the request. In this situation we must be sure that all request available for Spring (otherwise an exception similar to below can be thrown). To make that, you can define a listener in web.xml:
<listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
After calling /test URL, you should retrieve following entries in the logs:
shoppingCartRequest is :com.waitingforcode.scope.ShoppingCartRequest@2586b11c shoppingCartRequest is :com.waitingforcode.scope.ShoppingCartRequest@3bd5b945
If we try to use request scoped bean inside singleton bean, a BeanCreationException can be thrown at application context loading stage:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.waitingforcode.scope.ShoppingCartRequest com.waitingforcode.controller.TestController.shoppingCartRequest; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shoppingCartRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:381) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4701) at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5204) at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5199) at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.waitingforcode.scope.ShoppingCartRequest com.waitingforcode.controller.TestController.shoppingCartRequest; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shoppingCartRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ... 21 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shoppingCartRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:353) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1014) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:957) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480) ... 23 more Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:41) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:338) ... 28 more
What is session scope in Spring ?
Session-scoped beans are not so different from the request ones. They are also associated with purely web application context. Beans annotated as session-scoped are created only once for every user's session. They are destructed at the session ending.
Beans limited by session scope can be considered as web-oriented singletons because only one instance is present for a given environment (user's session). But remember that you couldn't use them outside web application context.
To see session-scoped beans in action, let's define one in configuration file:
<bean id="shoppingCartRequest" class="com.waitingforcode.scope.ShoppingCartSession" scope="session"> <aop:scoped-proxy/> </bean>
The way of retrieving it is the same as for request-scoped bean, with help of @Autowired annotation. We put exactly the same entry to the logs. It's done the following results:
shoppingCartSession is :com.waitingforcode.scope.ShoppingCartSession@3876e5d shoppingCartSession is :com.waitingforcode.scope.ShoppingCartSession@3876e5d shoppingCartSession is :com.waitingforcode.scope.ShoppingCartSession@3876e5d shoppingCartSession is :com.waitingforcode.scope.ShoppingCartSession@3876e5d shoppingCartSession is :com.waitingforcode.scope.ShoppingCartSession@3876e5d shoppingCartSession is :com.waitingforcode.scope.ShoppingCartSession@2f87fafc
As you can see, the first 5 prints represent the same object. The last one is different. What does it mean ? Simply, it means a new user who accessed the page with autowired session-scoped bean. We can observe it by opening the test page (/test) with two different browsers. Each will initialize a new session, and so create new ShoppingCartSession bean instance.
Regarding global session scope, it's reserved to portlet applications. Already confused ? So, let's explain shortly what the portlets are. Portlets are small Java web plugins able to generate semantic code (for example: HTML) snippets. They are based on portlet container and can process HTTP request exactly as the servlets do. But unlike the servlets, each portlet has different session. In this case, Spring provides a scope called global-session. Thanks to it, one bean can be shared through multiple portlets in the application.
This article added some of explanations for already approached scopes, singleton and prototype. Here, we discovered request and session-oriented scopes. The first one causes that new bean is created on every request. The second one initializes the bean at the same moment as the session. After the same bean's instance is available for whole session lifecycle.
Consulting

With nearly 16 years of experience, including 8 as data engineer, I offer expert consulting to design and optimize scalable data solutions.
As an O’Reilly author, Data+AI Summit speaker, and blogger, I bring cutting-edge insights to modernize infrastructure, build robust pipelines, and
drive data-driven decision-making. Let's transform your data challenges into opportunities—reach out to elevate your data engineering game today!
👉 contact@waitingforcode.com
đź”— past projects