#Autowired works only once.
What to do to make it wire the bean every time the Servlet is recreated?
My web-app (Tomcat6 container) consists of 2 Servlets. Every servlet has private fields.
Their setters are marked with #Autowired
In the init method I use
WebApplicationContextUtils
...
autowireBean(this);
It autowires the properties marked with #Autowired once - during the initialization of the Servlet.
Any other session will see these fields values, they will not be rewired after the previous session is destroyed.
What to do to make them rewire them each time a Servlet constructor is called?
a) Put the autowiring into the constructor?
Or better 2) get a web app context and extract a bean from there?
There seems to be some misunderstanding about how the container works. Servlets are essentially singletons, you don't get a new servlet everytime someone calls the server. Storing state in private fields on a servlet is pretty much an error.
What is the scope and life-cycle of the stateful part of your request processing? If it's just the life of the request then you can take whatever on your servlet is stateful and move it into another class. Then you can define a prototype bean for that class and use getBean at the start of the request to get a new one. If you want to start getting fancy you could write a filter that puts a new bean into a ThreadLocal at the start of each request.
If your state needs to span multiple requests, you need to start keeping state or a key that points to the state storage on the web session, or look into using a conversation framework.
Try using scope as prototype for that bean #Scope("prototype")
You may try to use #Scope("session")
Related
I have a callable type class. It is a annotated with #component. I would like to create multiple instances of the callable class. To do so, I am using the application context. The problem is it simply does not work.
Refer Bean scope you want to use:
https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch04s04.html#:~:text=2%20The%20prototype%20scope,method%20call%20on%20the%20container).
singleton - once for each IoC container, your application context
prototype- multiple beans for multiple object instance
request - in case of web aware app context, each bean to a particular HTTP request, and new instance for another
session- for each HTTP session.
global session - as what name says.
depending on your use select scope as well explained by #BeUndead.
I have been trying to understand spring beans. As per my understanding, by default all beans are singleton and a singleton bean with lazy-init property set to true is created when it is first requested and singleton bean with lazy-init property set to false is created when the application context is created.
So, in an application, when a user request comes in ( where each request is a separate thread), do all these threads share the same singleton beans when requested within the program/class?
Yes, if the bean is created with default scope, the bean is shared across threads. However, another scope can be used to achieve the behaviour you mentioned.
See: https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch04s04.html?
Yes, by default (scope == 'singleton'), all threads will share the same singleton bean. There are two other bean scopes, session and request, that may be what you're looking for. The request scope creates a bean instance for a single HTTP request while session scope maintains a unique bean for each HTTP Session.
For a list and description of all of the Spring bean scopes, check out: Spring bean scopes
The best way to understand this is to understand how #Autowired annotation works.
Or in other words to understand "Spring Dependency Injection".
You said, "
by default all beans are singleton
We use #Autowired when injecting one layer into another between two layers.
If exemplify: Suppose, I want to inject UserService UserController. UserService is a Singleton bean. Creates an instance from UserService and Stores its cache. When we want to inject this service with #Autowired annotation. This annotation brings the UserService stored in the cache.
In this way, Even if we do this inject operation in many classes.#Autowired inject an instance of UserService with singleton bean instead of dealing with one UserService at each time. It saves us a big burden.
This is the fundamental working logic of Spring Singleton Bean.
Also, Spring Ioc Container manages this whole process.
I have a Spring MessageListenerContainer added to a legacy application that initializes all it's services via a servlet (ie upon startup). The problem is that I need this servlet to be fully initialized (and thus have created a series of services modeled as singletons), however in my listener I get a NullPointerException. My approach is to set the load-on-startup of the first servlet to a lower number than the spring servlet, which should ensure that the former has been initialized. Then in my listener I have a an init method decorated with #PostConstruct which gets the references to my services, so something like:
this.userService = LegacyContext.getInstance().getManager().getUserService()
where the userService has been created in the servlets init() method. Problem is it doesn't seem to be initialized (it's null). What I've tried:
in the messageListener add an #Autowired WebApplicationContext, the idea being that the messageListener should only be created once the WebApplicationContext has been created (and thus the legacy servlet been created)
created another bean which has an autowired WebApplicationContext, and add that as a dependency to the messageListener, a variation of the approach above.
created a reference to the service beans in applicationContext.xml and added depends-on to the bean above
I eventually do get a reference to the service after everything is loaded, but I don't understand why it's not available in the messageListener? The first servlet should have been initialized by the time it gets to the listener, because of the dependency.
This question already has answers here:
How does a ScopedProxy decide what Session to use?
(3 answers)
Closed 7 years ago.
I am trying to use session scope bean in spring mvc with following bean definitions
<bean id="test" class="com.gk.testScope.Test" scope="session">
<property name="name" value="mytest"></property>
<aop:scoped-proxy/>
</bean>
Code for controller
#Controller
public class MyController
{
#Autowired
Test t;
#RequestMapping(value="test1",method=RequestMethod.GET)
public String test1(HttpServletRequest request) {
System.out.println("name"+t.getName());
request.getSession();
return "test1";
}
}
on running above code it prints mytest even before starting any session. Can some one explain what session scope doing here?
Below line of code does not actually create session, it gets the session already created by the servlet container.
request.getSession();
Now comes the important stuff. Bit tricky to get at first if you are new to Spring scopes.
Injecting a singleton bean in another singleton bean is intuitive and makes sense. How about you want to inject a bean which is not Singleton into a Singleton bean? The injection should happen on demand right ? So to configure this, we cant directly inject the bean which is not singleton. We inject a proxy for a non singleton bean, which in turn gets a new bean injected on demand.
<aop:scoped-proxy/>
The above tag helps create a new bean for every session(because the scope is "session") created on the server and injects in the controller on demand.
I am sure someone can explain in much simpler manner. Hope this helps.
The spring framework provides an inversion-of-control coding framework; that means you only has to concern your business logic and write down it as handler function, the spring framework would take care the rest of things and call your handler function.
For example, in a mvc spring framework, the http request handling, http session handling, the beans life-cycle management are all done in spring-framework and you only needed to write the "test1()" function that is called when client hit the URL "/test1".
When client start a HTTP session with spring web server, the framework will create a session scope, and all session scope beans will be created. When client sends a HTTP request, the framework will create a Request scope and all create request level scope beans.
Please see 6.5 Bean scopes from spring reference doc.
I have read from the question How to gain access to a ServletContext instance from any method? that if I want to access the Servlet Context from any class in my Java web project I can declare a static field that points to the ServletContext from ServletContextListener, but a static field is a bad practice in Java web applications because the GC can't collect it until the JVM is turned off (correct me if I'm wrong in this point). Is there another way to access the ServletContext without using a listener or receiving it as a parameter? There is another workaround for solve this problem? I'm using JSF 1.2 and JBoss 5.1 GA for the Web Application.
Note: I know I can use
(ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext();
to access the ServletContext, but there is a method that runs at startup that needs to access the ServletContext and the FacesContext.getCurrentInstance() has not been initialized.
UPDATE:
We need to load some IP's from the web.xml into String constants when the web application starts up. To do this, we have created a Singleton class that loads the context-params in variables and then fill the String constants with some values of the Singleton class. This Singleton class manages lot of data and is giving out of memory exception errors. To fix this problem, we're modifying the Singleton class to be a simple class that is loaded as a ServerContext attribute, but then the String constants can't be loaded for the absence of the instance of this (not anymore) Singleton.
I'm not sure why you need a singleton. Just create one bean which you store in the application scope.
#Override
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
Set<String> ips = parseContextParamSomehow(context.getInitParam("ips"));
Manager manager = new Manager();
manager.setIps(ips);
context.setAttribute("manager", manager);
}
It'll be available by #{manager} in EL context. Also as managed property of an arbitraty JSF managed bean. An alternative is to create an application scoped JSF managed bean and do the job in its constructor, but you're then postponing its construction to the first HTTP request which involves the bean.