Spring Boot How can i easy Scope Request bean in Async method? - spring

Spring boot
How can i easy use bean with Request Scope in async method.
When i try execute got exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bean ! class': 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.

I found a simple solution to this error.
I've initialized the requestScope bean.
which contains #Async method.
Now every request(rest) call with controller receives a new instance of bean.

Related

Spring Boot HttpServletRequest Request Scope Bean?

It would seem that HttpServletRequest is a request scope bean, but I have not yet been able to find any documentation on this.
Does anyone know where this is documented or where in the code base it is created?
The HttpServletRequest is normally created and managed by servlet container (e.g. Tomcat) but not Spring. You normally do not need to define it as a spring bean unless you are doing something special. So technically from the spring 's point of view, the HttpServletRequest does not have any scope as it is not a spring bean.
But even if you need to define a HttpServletRequest bean for some reason, by default it will be in the singleton scope. (see the scope table in this).
The relationship between HttpServletRequest and a request scope bean is that Spring will make sure whenever the servlet container process a new HttpServletRequest , it will create a new request scope bean instance in case you need to access it during processing this HttpServletRequest. And this request scope bean will be destroyed after the servlet container finish process that HttpServletRequest. Such behaviour is also mentioned in the above link as :
Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext

BeanCreationException for Session scoped bean in #async method

I am stuck into a problem of accessing a session scoped bean in async method.
My Bean definition:
<bean name="ABC" class="java.util.HashMap" scope="session">
<aop:scoped-proxy />
</bean>
My controller class has the annotation '#EnableAsync'.
I am autowiring the class with async method in controller :
#Autowired
AsyncWorker asyncWorker;
When the async method is called, it tries to get the session bean defined above by the following line of code:
Map<String, Object> sessionMap = context.getBean("ABC");
This ends up with the following error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.ABC': Scope 'session' 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.
RequestContextListener is also defined in my web.xml.
All works good when the call is synchronous.
Starting a new thread or using the Async method results in the same error.
Any help on this would be appreciated.

Does an Object in Spring created every time we write getBean()?

I have read that whenever we do getBean() in spring, it returns desired object.
So does it mean, if i write call getBean() 1000 times, thousand object will be created ??
If yes, Than how Spring manages these objects ?
if No, Please explain how Spring works with respect to object creation ?
Is there something Object pool kind of concept ?
Please clarify my doubts. I am new to spring and is very confused whether spring framework is created to make our task easy or to make things more complicated.
Spring seems to be a web of XMLs :(
From the Spring Framework documentation on singleton bean factory scope:
The singleton scope
Only one shared instance of a singleton bean is managed, and all
requests for beans with an id or ids matching that bean definition
result in that one specific bean instance being returned by the Spring
container.
To put it another way, when you define a bean definition and it is
scoped as a singleton, the Spring IoC container creates exactly one
instance of the object defined by that bean definition. This single
instance is stored in a cache of such singleton beans, and all
subsequent requests and references for that named bean return the
cached object.
To sum it up, no, Spring will create only a single instance of each bean in a bean factory unless you change the default scope of singleton to some other bean scope.
Other bean scopes include:
Bean scopes
singleton (Default) Scopes a single bean definition to a
single object instance per Spring IoC
container.
prototype Scopes a single bean
definition to any number of object instances.
request Scopes a single bean definition to the
lifecycle of a single HTTP request; that is, each HTTP request has its
own instance of a bean created off the back of a single bean
definition. Only valid in the context of a web-aware Spring
ApplicationContext.
session Scopes a single
bean definition to the lifecycle of an HTTP Session. Only valid in the
context of a web-aware Spring ApplicationContext.
global session Scopes a single bean definition to the
lifecycle of a global HTTP Session. Typically only valid when used in a portlet
context. Only valid in the context of a web-aware Spring
ApplicationContext.

How to instantiate Spring bean with custom scope and #Autowired dependencies?

In our project, we use Spring request scoped beans. Now we've a requirement to support async requests and request scoped beans don't work for child threads. I'm aware of RequestContextFilter and it's "support" for async but it appears that RequestContextFilter expects the main thread to wait for the child threads to finish, which isn't the case for us. Our main thread immediately returns after spawning new threads using #Async annotation and DispatcherServlet clears out the RequestContextHolder. Thus when the child threads get to the point where they need a request scoped bean, #Autowired fails.
I'm also aware of SimpleThreadScope but it doesn't clean up thread-local attributes and in a thread-pooling situation, is not only dangerous to use but downright useless.
What I need is a custom scope. So far, I've found 3 useful examples but all of them fall short in that the beans they instantiate as part of the custom scope are plain POJOs without any dependencies. Needless to say that's non-existent in a real life application. Can anyone suggest a way to instantiate custom scoped beans that have #Autowired dependencies on beans from other scopes?
What I found so far:
https://github.com/spring-by-example/spring-by-example/tree/master/modules/sbe-thread-scope/src/main/java/org/springbyexample/bean/scope/thread
https://github.com/billkoch/spring-async-mdc
Spring Bean Custom Scope JMS
Continuing the discussion from the other question's answer here...
See the Spring Documentation about scoped beans as dependencies.
.
I'm referring to the <aop:scoped-proxy/> which is what the link points to. Each time the autowired field is referenced, your custom scope's get() method is called to lookup the instance based on some criteria.
.
I understand I can look up the dependencies (though unsure how, a scope isn't a bean, perhaps I need to pass application context during instantiation?). What I don't understand is how to inject those dependencies into my bean if those're marked #Autowired? Or are you saying the custom scoped bean shouldn't have #Autowired dependencies?
It works automatically; Spring injects a proxy for the bean and the scope.get() is invoked on every method call on that bean, returning the specific instance you want in the context of the current invocation.
Take a look at the AbstractRequestAttributesScope to see how it works (in that case, gets the instance from the HTTP Request and, if it doesn't exist, creates it).
So, your code calls foo() on the proxy; the framework calls the scope to get the desired instance and then calls foo() on that instance.
The exposed methods you wish to call must either be on an interface or not declared final.

Returning status from long-running session bean method

I am using JSF 2.0 with RichFaces 4.2.2 running on Glassfish 3.1.2. I have created local stateless session beans with a long-running method that will be called by the JSF managed bean.
I would like to be able to push status information from the session bean back to the managed bean so that I can use something like RichFaces a4j:push to get the status to the browser. I believe this would require that the call to the session bean method would be asynchronous. Are there patterns for pushing information from session beans back to the front end as the session bean is processing the method call?
Stateless session beans (SLSB) are not supposed to hold any state (read: instance variables which are altered by the methods) because they are shared between all clients applicationwide. So they are useless to you if you need a session bean with some state which you can update during the process and which the client can request anytime. You need a stateful session bean (SFSB) instead. If you inject the SFSB in a session scoped JSF managed bean, then you'll be able to request the proper status from it and push it to the client throughout the HTTP session.
To understand the difference between SLSB and SFSB better, you may find this answer helpful: JSF request scoped bean keeps recreating new Stateful session beans on every request?

Resources