Injecting request scope beans into singletons with RESTeasy and Spring
Spring has a nice feature, which is often overlooked: a bean with shorter life-cycle can be injected into a bean with a longer life-cycle. A classic example is singleton for MVC controller and a request-scope bean for DAL. This is achieved in Spring with defining a proxy bean like this:
<bean id="booksDao" class="my.dal.BooksDao" scope="request"> <aop:scoped-proxy /> </bean> <bean id="booksFacade" class="my.web.BooksFacade"> <property name="dao" ref="booksDao"/> </bean>
This way, booksDao can be accessible from any beans processing the request, and Spring will ensure it's the same instance during the same request, and different instance for different requests.
Under the hood it's implemented with a proxy object. So booksFacade in reality holds a reference to a proxy object, which looks up the current request context in ThreadLocal storage and forwards all your method calls to the request-scoped booksDao.
If your application is Spring based all-around, the necessary preparations are done in Spring's DispatcherServlet.
But if you are using RESTEasy (or jersey), you have to use the different servlet. So when your booksFacade will try to access its dao, it will not find the request context in ThreadLocal storage and throw an exception.
Fortunately, Spring provides 2 alternative ways to fill the request context when you are not using DispatcherServlet. One is RequestContextListener and the other is RequestContextFilter. You need to add one of them to your web.xml. Filter better suits the cases when some URLs should have this context and some should not.
In most cases, you want all requests to pass through Spring handler and have a correct request context. To achieve this, you simply have to add to your web.xml these lines:
<listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
Now the booksDao proxy will work as expected, and you can access the request scoped beans from singletons when necessary.
</meta> </meta> </meta>