When does JSF creates a session & what does it puts in a session map? - jsf-2

I am running Mojarra 2.2.0.
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
The managed bean action method is-
public void action() {
HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
.getExternalContext().getSession(false);
System.out.println(session.getId()); // not null for stateful views
}
For stateless views session.getId() throws NPE
For views which are not stateless-
Firing a GET request, there is JSESSIONID=340041C96D5AA446D761C3602F54A76D
I read it here that-
For client side state saving mechanism, JSF won't create the session
and will store the view state in a hidden input field with the name
javax.faces.ViewState in the form whenever necessary.
Further, it's mentioned here that
JSF will indeed autocreate the session because the JSF view state has
to be stored over there. If you set the JSF state saving method to
client instead of server, then it won't be stored in session and hence
no session needs to be created
I think the above line is a source for trouble for me.
If you set the JSF state saving method to client instead of server,
then it won't be stored in session // FULLY AGREED
and
hence no session needs to be created. // This confuses because for
client side saving mechanism, a session id gets generated by the
servlet container & hence there is a session associated with the
request.
In reference to the discussion which I had with BalusC in this question,
I created a HttpSessionListener-
#WebListener
public class MyHttpSessionListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
Thread.dumpStack();
}
public void sessionDestroyed(HttpSessionEvent event) {
}
}
See below attached screenshots(these 2 screenshots are for version 2.0.3, there must have been an old bug due to which the session was getting created)-
Libraby (Mojarra 2.2.0)-

When does JSF creates a session
Eaiest way to naildown this is creating a HttpSessionListener, putting a debug breakpoint on sessionCreated() method and inspecting the call stack who needed to get the session for the first time (and thus implicitly needs to create it).
In below example you will see a chain of getSession() calls in the call stack. You will see that FaceletViewHandlingStrategy.renderView() method is the one calling it for the first time.
After you click on FaceletViewHandlingStrategy.renderView() line in debugger's call stack, you will get into its source code (Maven will load source code automatically, otherwise you need to manually attach it).
You see, when server side state saving is enabled and the view to render is not transient (stateless), then JSF will implicitly create the session, just to ensure it's created on time in order to save the view (if the session was created later, e.g. during render response phase, you would otherwise risk exceptions like this Adding <h:form> causes java.lang.IllegalStateException: Cannot create a session after the response has been committed).
You'll in the source code also immediately see that when the state saving method is set to client, or when the view is stateless as in <f:view transient="true">, then JSF won't anymore implicitly create the session. Older JSF versions may do that as you figured, but this is to be accounted as a bug and ought to be fixed in a newer version.
If you would like to ensure statelessness and avoid accidental/unforeseen session creation, then you could just throw new IllegalStateException() inside sessionCreated() method. When that happens, you just have to look in call stack who's responsible for creating the session and then fix/change the code to not do that anymore.
what does it puts in a session map?
Under the covers, ExternalContext#getSessionMap() delegates to HttpSession#setAttribute()/getAttribute()/removeAttribute(). You can listen on those methods using a HttpSessionAttributeListener.
In below example you will see that ViewScopeContextManager.getContextMap() line calls SessionMap#put() method in order to put something in the session map. When you unfold the event argument, you will see the session attribute name and value, which is com.sun.faces.application.view.activeViewContexts and an empty ConcurrentHashMap respectively.
Indeed, I was using a #Named #ViewScoped which was referenced by an value expression on the particular page (you see EL resolver and Weld resolver further down in call stack). When you click ViewScopeContextManager.getContextMap() line in call stack, you'll see that it was just preparing a map in session scope in order to store view scoped beans.
That's just one example. There are more things which could be stored in the session. Using a debugger this way and inspecting the associated source code will tell a lot about the Why.

Related

When to explicitly close ResourceResolver in Sling

I've read on this blog about how to use resourceResolver properly. The author quotes
If you open a JCR session of a Sling ResourceResolver, you are also
responsible for closing it. On the other hand: If you get passed a
ResourceResolver or a Session object, do not call logout() or close()
on it.
I'm not able to grasp this concept, may be because of no code example in this case.
From what i know, i can get a ResourceResolver object via either request.getResourceResolver() in servlets, using #Reference SCR annotation in OSGi components, jsp's implicit resourceResolver object, using sling.getService() in jsp, and also via adapting to ResourceResolver object.
In all the ways of getting resourceResolver object, which ones should i close myself and what is the session associated with each of these objects ?
Think of it like a File resource.
if you open it, you are responsible for closing it
if you use a reference to the File, then it is not your responsibility to close it
Therefore, your code should open & close in the same scope.
If you obtain a resourceResolver FROM a resource, you did not open the resolver and you do not need to close it.
In the example from the blog, they generate a session from session = repo.loginAdministrative() (Repository no longer has this method); thus is responsible for calling session.logout() in the same scope (using the finally {...} block).

Getting a scoped component from a IDocumentStoreListener

I have an ASP.NET 5 app using RavenDB, and I'm trying to create an attribute that will create a "Changeset" document with the keys of all the documents that were stored by the action.
For that purpose, I created an ActionFilterAttribute instantiated via ServiceFilterAttribute, which is registered as Scoped, that sets a flag on another Scoped component, let's call it ChangesetAccessor, which holds the list of changes.
The IDocumentStore is obviously a Singleton, and the listener (IDocumentStoreListener implementation) is manually instantiated. It needs access to the current ChangesetAccessor, so I thought giving it a reference to the IServiceProvider so it can call GetService<ChangesetAccessor> as needed would be enough, but it is receiving a different instance.
How can I get the ChangesetAccessor for the "current request" from my listener?
You can actually access RequestServices off of the HttpContext to get scoped instances. It's kind of backwards, and really will depend on Microsoft.AspNet to do it, but it will work for your situation; interestingly, IHttpContextAccessor is a singleton, too, though it gives you a scoped value.
// injected:
IHttpContextAccessor httpContextAccessor;
// in your method:
httpContextAccessor.HttpContext.RequestServices.GetService<ChangesetAccessor>()

Lifecycle of FacesContext?

While going through the javadoc of FacesContext, I came across this sentence
The instance remains active until its release() method is called, after which no further references to this instance are allowed. While a FacesContext instance is active, it must not be referenced from any thread other than the one upon which the servlet container executing this web application utilizes for the processing of this request
Does this mean that FacesContext will never go for garbage collection, and the instance will be destroyed only when the current-webapplication stops (server is stopped)?
Is FacesContext following singleton pattern? In that case, how will it behave when multiple request and coming for rendering response simultaneously as it serves only one request per time?
Does this mean that FacesContext will never go for garbage collection, and the instance will be destroyed only when the current-webapplication stops (server is stopped)?
No, you read it wrongly. The FacesContext lives as long as a single HTTP request. It will (actually, "can" is a better word) not immediately be GC'ed if you incorrectly reference it anywhere in your own code beyond its scope. E.g. as a property of a session scoped managed bean which lives longer than a single HTTP request:
#ManagedBean
#SessionScoped
public class BadSessionBean {
// Bad Example! Never do this! Not threadsafe and instance can't be GC'ed by end of request!
private FacesContext context = FacesContext.getCurrentInstance();
}
If you aren't doing that anywhere in your code, and thus you're always obtaining the current instance in method local scope, then it will have the chance to be properly GC'ed.
#ManagedBean
#SessionScoped
public class GoodSessionBean {
public void someMethod() {
// OK! Declared in method local scope and thus threadsafe.
FacesContext context = FacesContext.getCurrentInstance();
}
}
Please note that this GC behavior is not specific to JSF/FacesContext, it's just specific to basic Java in general.
Is FacesContext following singleton pattern? In that case, how will it behave when multiple request and coming for rendering response simultaneously as it serves only one request per time?
No, it's definitely not a singleton. It's a ThreadLocal instance which is created by FacesServlet right after the service() method is entered and destroyed by the FacesServlet right before the service() method is left. Thus, there's only one instance per request (and thus not per application). Note that one HTTP request counts as one separate thread. There can be multiple threads (read: requests) and thus there can be multiple instances of the FacesContext during application's lifetime. Its main pattern is the facade pattern, but that's further not related to it being a ThreadLocal.
See also:
java threadlocal singleton - what is it?
How to initialize an API in servlet environment
Examples of GoF Design Patterns in Java's core libraries

Is it thread unsafe for a #SessionScoped bean to maintain a reference to its HttpSession?

Taking a look at the unrelated portion of this answer to another question, although I understand why the references to request and response are threadunsafe in the question's example, why is it threadunsafe for a SessionScoped bean to reference the HttpSession to which it is bound?
#SessionScoped
public class SessionManager {
HttpSession session = null;
...
#PostConstruct void initialize() {
this.session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
}
private void onLogin(#Observes #LoggedIn User user) {
// (1) housekeeping stuff
// (2) destroy older, duplicate login session, if user did not previously
// logout, in which case it would be really handy to have a reference
// to HttpSession.
}
}
While implementing the example I sketched out, above (see OP), I realized that maintaining a reference to a session is not good because it is indeed thread unsafe. It is smelly code.
I was surprised to see that not only did the old session get invalidated but the current session was destroyed by the container as well! So the user was logged out in both browsers. Later, I came across this Websphere best practices documentation, which, although I am not using Websphere, helped me realize that caching the session is not good practice at all:
Avoid trying to save and reuse the HttpSession object outside of each servlet or JSP file.
The HttpSession object is a function of the HttpRequest (you can get it only through the req.getSession method), and a copy of it is valid only for the life of the service method of the servlet or JSP file. You cannot cache the HttpSession object and refer to it outside the scope of a servlet or JSP file.
There is no need to cache HttpSession; one can instead cache the session ID and when a duplicate session is discovered simply add the previous duplicate session's ID to Set<String> invalidatedLoginSessionIds. Then refactor the application such that immediately upon receiving a request from the old session invalidate the old session and redirect the old browser to the appropriate facelet. If no such request is received the old session will simply time out and be destroyed anyway, so no worries there.

Why is CDI-Event creating a new instance instead of using existing Oberserver?

I am facing a problem with CDI on JBoss AS 7.1.1
I have two JSF-beas, where one has the CODI ViewAccessScope (Bean A) which shows all entities, and the second is plain RequestScoped (Bean B). Each Bean get a, so called, Presenter injected which takes care of all presentation logic. So far so good.
The Presenter from Bean B is responsible for creating a new entity (calling service...bla...blubb) and when everything is done Bean B is redirecting to another page but since Bean A now has to reload its content I introduced the JEE-6 Observer.
In detail: Both Beans (A & B) get a particular Presenter injected (which has a backrefrence to the jsf-bean via a interface). Bean-B-Presenter fires an event after the entity was successfully created, so that then Bean-A-Presenter (the Observer) can reload the data and notify Bean-A about the changes.
The Problem: I am getting as NullPointerException when the observing Presenter (A) reloads its data because the reference to Bean A is lost. The reason why this happens is because CDI is obviously creating a new Presenter-object (its annotated with #Named) instead of using the one that is coupled with Bean-A.
Workaround: when I use Bean-A as the Observer than everything works.
My code is pretty much the same as seen in the link I added. I don't understand why a new instance is created when firing the event.
UPDATE regarding LightGuards comment:
The presenter beans are just annotated with #Named (which should be Dependent-Scope by default).
I had a look at the Weld-Documentation and it looks like this scope is somehow isolating my beans from each other. I need the presenters to be a new instance, each time a view (jsf-bean) gets initialized (so no Singletons). On the other hand I want to be able to send events between them, meaning that only the already existing instances get notified (not that a new instance is created).
I just did a test with the presenters being RequestScoped. This doesnt work either because now on every HTTP-Request I get a new Presenter even though the view (jsf-bean) to which it belongs is ViewAccessScoped. SessionScope of course works...but this would result in the wrong design.
Sounds like you'll need to create your own scope for this usecase. None of the default scopes sound like they fit your need. Another option would be to look at MyFaces CODI and the conversation scope they're written.
Please ensure that your observers aren't private.
And you have to ensure that you redirect correctly.

Resources