Reputation: 477
I am experiencing a behavior in my application I do not understand. I have a servlet (Servlet1) that accepts a request, invalidates the current session, creates a new session, and then redirects on the request to a JSF page which references a @Named @SessionScoped bean (Bean1). Both the servlet and the bean @Inject another @SessionScoped bean (SharedBean). The first time I visit my servlet URL everything works correctly. However, the second time I visit the URL the @Named @SessionScoped bean is creating a new instance of sharedbean.
So what I would like to happen is this:
This is happening correctly the first time I access my servlet URL but what is happening on the second invocation is this:
This doesn't seem like the correct behavior to me. I know I am missing something here and I would appreciate someone explaining it to me. Code is below:
Servlet1:
@WebServlet
public class Servlet1 extends HttpServlet
{
@Inject
private SharedBean sbean;
public doGet(HttpServeltRequest request, HttpServletResponse response)
{
HttpSession session = request.getSession();
session.invalidate();
session = request.getSession(true);
this.sbean.initialize();
response.sendRedirect(newURL);
}
}
Bean1:
@Named
@SessionScoped
public class Bean1 implements Serializable
{
@Inject
private SharedBean sbean;
public void actionMethod()
{
this.sbean.execute(); // New instance being created here on 2nd access!
}
}
SharedBean:
@SessionScoped
public class SharedBean implements Serializable
{
public void initialize() { /* do some work */ }
public void exeucte() { /* do some work */ }
}
Upvotes: 1
Views: 244
Reputation: 1900
Because each time the servlet is requested you invalidate the session. So the container creates a new bean or provides another instance. You have to invalidate the session after a certain period of time of inactivity of the user or some other endpoint.
SessionScoped means the bean instance is valid for multiple requests. But you have to decide what a session means for your application. In most cases a session is associated to the time a user logs in and logs out. So it is comprised of multiple requests. So a session is valid for multiple requests and is the same for different servlets. The session is managed by the servlet container (e.g Tomcat) and an instance of the session object is provided via a ServletContext instance.
You create a new session everytime your servlet is requested. That means the container just creates a ServletContext for this single request and always binds a new bean instance of your SharedBean to that context instance.
UPDATE due to comment.
In this case i would not suggest to let the container manage the bean injection. Because you never know at what time the bean instance is created and associated with a SharedBean instance. I think the reason is the issue that you create a new session within you servlet request method. The bean instances of the SharedBean can't be the same in this case, because the container creates an new instance of SharedBean and invalidates the shared bean instance bound to the servlet.
It would be better in this case to create the SharedBean within the servlet, pass it to the session context as a parameter and use the SessionContext within the bean to fetch the SharedBean instance.
UPDATE due to COMMENT
The injected beans are managed by the container. Means the container is responsible for creating and destroying the bean. If you create a new instance of the bean the reference (address) or bean instance is decoupled from the servlet container and not managed anymore by the container. So the shared bean reference is not available for your managed bean Bean1
UPDATE due to COMMENT
The answer to the problem is that the instance of the SharedBean which you create within the doGet method of the Servlet method is not communicated to the servlet container and therefor not available for the managed bean Bean1.
Upvotes: 1