Coming from plain old DI of Spring I can't figure out how to choose scopes properly while writing with CDI.
In Spring all my services have singleton scope by default, which I suppose maps to application scope in CDI (or even #Singleton). I know for e.g. logged in user information I need to use Session scope and for e.g. form params I need request scope.
Say I have a bean that hides external service API calls. It is completely stateless. Should I put it as #Singleton or simply application scoped? Or let it be created on every request (possibly bad option).
Is this correct to inject everything everywhere? In Spring I create my data objects by new. Should I do the same in CDI or simply #Inject them?
Are you only using CDI? or a Java EE 6 container? If you have a stateless class that is used for service calls, then I would recommend using #Stateless, which is from the EJB spec (so you would need a Java EE 6 container) It isn't a singleton, but it doesn't get created on each request either. I believe it is more closely bound to the session, but since it is stateless, instances can be pooled and shared. If you are only dealing with CDI, I believe Singleton matches more directly to Spring's singleton, but I would recommend using ApplicationScoped because it provides a proxy which makes serialization of beans that use it easier.
#Service
#Scope("prototype")
public class CustomerService
{
......
}
Just add #Scope("prototype") annotation to your component.
Is there a reason you would need the bean to remember it's state? If you are using something like a web client, that is a better place to store state in say, session scoped managed beans (assuming jsf), or whatever equivalent for your case. On the back end server side your EJB's would be better kept as #stateless to keep overhead to a minimum and help with the 'keep it simple s..." paradigm. And in case this works, just declare #Stateless on your bean. Unless there is a reason to use a singleton, again it is better to use a stateless bean if you want to go with a Java EE container for your services.
Stateless beans are not really being recreated with every request. That is the purpose of the pool. The app server keeps a ready supply of stateless beans on hand, and if it gets busy, it will make more, and if it quiets down, it will empty some out.
Related
We have a Web Application exposing both Web Resources (REST) and JMS MessageListener. Spring is the framework used to define and inject beans.
We defined beans in the scope "request" to store information usable for Web Resources. We would like to use those beans also in the JMS MessageListener, but the "request" scope does not exist and cause an exception.
One solution of this problem is to use a custom scope of type "thread" as implemented with the "SimpleThreadScope" of Spring. But the destruction of the beans is not implemented in this class. I know there is a way to implement this with the "Spring custom scope thread by example", but I prefer letting the Application Server manage the thread pool.
Do you have any other idea/suggestion about this issue?
Important aspect: the beans created in the scope are used as by resources as well as by JMS Message Listener.
Let's take an example.
Imagine we have the following classes:
Class BeanInScope1
Class WebResource1
Class Service1
Class MessageListener1
The "Service1" uses the "BeanInScope1", and the "Service1" can be called either by "WebResource1" or by "MessageListener1", meaning that the "BeanInScope1" msut be created in the same way by "WebResource1" and "MessageListener1".
Hope this example shall help...
It is needed to define Spring scope which will provide a proxy to the beans and reload/recreate target beans when say an event occurs. The behavior is similar to session beans, except there is no http session.
Does Spring provide a way for such bean proxing and scope manipulation?
UPDATED
Say that it is need to change externalUrl which is used to send http requests. So the application has to switch to new bean with new http connection pool created.
When bean autowired directly it is imposible to recreate it, especially when it is used in many places. So I search some way to inject a proxy instead of it and recreate target instace without altering caller code.
It is possible. I can't tell you exactly how to do it, but if you're able to, something like Spring Cloud Config would be exactly what you want. If you can't adopt that, I would start digging into the source code. The class you'd want to start with is the RefreshScope - from there, you should be able to figure out how it works and how it re-creates beans. I'm sorry that I can't provide more direction.
I want to expose some functionality of my existing JEE7 web app using a SOAP based #WebService. Can/should this service inject my app's CDI beans? How do #RequestScoped, #SessionScoped, and #ApplicationScoped CDI beans behave, given that there's no HttpServletRequest to identify the current session or request? ie. How do they get looked up?
My observations:
#ApplicationScoped seems to work as expected
#SessionScoped seems to behave like request scope in that a new bean is created each time the web service is called, but it is subsequently accessible from other beans up until the service completes
#RequestScoped beans don't seem to be looked up property - eg. if my webservice injects two #RequestScoped beans, then one of those injects the other one, a new instance is created, rather than the first one being injected
My idea was to use the #Dependent annotation to make my session beans behave like request beans when injected into my #WebService, but this isn't working due to the request scoped behaviour noted above. I could just use my #SessionSoped beans as they are, but I'm concerned about the memory overhead since a new bean would be created for every web service request, and then persist for some 30 minutes or so, rather than being destroyed once the service has completed.
Any clarification or ideas would be appreciated!
I am new to ejbs and cdi. To my understanding a stateful ejb stores the data in the instance variables and destroys the stateful ejb after the request is finished.
I recently attended an interview where the interviewer asked me what kind of ejb would I use in an online shopping kind of application.
If I have to do it without ejbs, I create a HttpSession and then add the user interest in the session and then show him another page to continue or make the payment or exit.
If I want to accomplish the same using stateful ejbs, I dont understand why should I use stateful ejbs, what is its significance? Because once the request is completed the ejb is destroyed and the user interest/cart-details are destroyed.
Secondly what I am not able to understand about cdi is, suppose I am injecting the service class into my servlet, because injection happens only once there will be only one instance of the service class. When more than two requests come the instance variables of the stateful ejb get corrupted. So I guess when I am using stateful ejbs I have to use #RequestScoped annotation. Am I right?
Stateful session bean will allow you to store the same state as an http session. Few advantages over using http session that I can think of:
Scalability - Your SFSB can be deployed on another server and scale independently using remote interfaces
Non-web clients - You can use SFSB to maintain state for a non-web client where http session will not be available
The other benefits that come with using an EJB
To hold a reference to a stateful EJB in a servlet you should use #SessionScoped with #Inject as indicated in this answer
Correct me if anything is wrong.
As I understand, all Spring functionality, namely DI works when beans are got thru
Spring Context, ie getBean() method.
Otherwise, none can work, even if my method is marked #Transactional and I will
create the owning class with a new operator, no transaction management will be provided.
I use Tomcat 6 as a servlet container.
So, my question is: how to make Servlet methods managed by Spring framework.
The issue here is that I use a framework, and its servlets extend the functionality of
basic java Servlets, so they have more methods. Still, web.xml is present in an app as usual.
The thing is that I do not control the servlets creation flow, I can only override a few methods
of each servlet, the flow is basically written down in some xml file, but I control this process
using a graphical gui.
So, basically, I only add some code to a few methods of each Servlet.
How to make those methods managed by Spring framework? The basic thing I need to do is
making these methods transactional (#Transactional).
comment to Bozho:
#Bozho Let's see. In these servlets' methods I work with framework capabilities, let's say special variables that are got and saved in the current session. And what is needed, is looping through those framework-based collections while saving some values in a database. What you suggest is introducing a new very complex object, so that it could be passed to a service layer. (Service layer will not know anything about framework, its classes and objects kept in current Session! First, we "wrap" framework based collections to such a object, so copy everything into it. Then, again, the Service layer method should either save changes in a database or, worse case, return a new complex object so that Servlet framework method could update framework variables depending on the result of Service layer method execution. It is a workaround but do you think it is a good idea?
You can also define your servlets directly in the Spring application context. You'll need a "proxy" servlet registered in web.xml and delegating to the servlet instance which is configured as bean in the applicationContext.xml. Proxy servlet is configured with the name of the target servlet bean, it discovers this bean via WebApplicationContextUtils.getRequiredWebApplicationContext().getBean(...) and delegates all the processing to the target servlet. In this case an instance of your servlet is completely managed by Spring.
I'd suggest restructuring your code - making servlet methods transactional is not a good thing to do. Put the transactional logic in a separate, service class, and either
obtain these spring-managed classes by WebApplicationContextUtils.getRequiredWebApplicationContext().getBean(..) or
in your servlet init() method obtain the ApplicationContext with the above method and call appCtx.getAutowireCapableBeanFactory().autowireBean(this). This way you can inject the transactional classes in your servlet as if it was spring-managed.
Now, you can do all this, but it is definitely not a beautiful way to go. I'd suggest using Spring MVC or any other MVC framework (which support spring integration of its components)
If this is all not possible, as a last resort I think you can use #Configurable (on your servlets) with a <context:load-time-weaver/>.
You should take a look how Spring proxy filters:
http://grepcode.com/file/repository.springsource.com/org.springframework/org.springframework.web/3.0.2/org/springframework/web/filter/DelegatingFilterProxy.java
In theory you could easily make the same sort of proxy for servlets and DispatcherServlet is sort of a proxy.