A colleague asked me last week about the managed beans and whether a requestScoped bean would be loaded for every request. It’s something I had inadvertently already proved but forgotten. It’s always worth clarifying though and of relevance to more than just managed beans, but anything defined in the faces-config.

All objects defined in the faces-config are defined as a variable name mapping to a class. So for a managed bean like this:
<managed-bean>
<managed-bean-name>openLogBean</managed-bean-name>
<managed-bean-class>org.openntf.domino.xsp.XspOpenLogErrorHolder</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

The variable name is openLogBean, which will relate to an object created from a Java class called XspOpenLogErrorHolder, and it’s lifetime should be for the session. But when is it instantiated? The answer is that it is only instantiated when any XPage code is encountered that uses that variable name, openLogBean. The faces-config itself does not instantiate the bean, it just provides a mapping from the variable name to the Java class, and defines in which scope it should be stored and any default properties (as managed properties). It then continues to exist for the duration of that session, so until the user logs out (providing your log out code clears sessionScope), or for 30 minutes (or whatever the session timeout has been set to in the Xsp Properties file) after the HTTP session has ended. You can verify this by looking at the sessionScope map, where you will find the bean.

If the scope had been request, then at the end of that request, the object would have been recycled and removed from the requestScope map. This is where openLogBean used to reside, but it was moved to support use cases where the catch block redirected to a specific XPage. (The server-side redirection started a new request, so render response for the original page was never reached, so the openLogBean that had the errors was trashed before it could be outputted.)

But, as you can see, now we have a problem. There is an instance of openLogBean added to sessionScope and persisting there until the scope is flushed. The solution can be found in the afterPhase event of the OpenLogPhaseListener. After outputting the error logs, the code calls sessScope.put("openLogBean", null);, which removes the bean from sessionScope. It’s then re-instantiated only when any XPages code calls openLogBean again.

ValueChangeListeners are also defined in faces-config as managed beans. Usually they are request scoped, which makes sense because you only want to capture whether the value has changed. But these have a shorter lifetime. They are only instantiated during the Process Validations phase and are removed during Invoke Application phase. Again, that makes sense, because until the value submitted from the browser has been validated, there’s no point in checking whether the value has changed, because it can’t be stored at all. Equally, after Invoke Application, any business logic to deal with the changed values will have been triggered, so the ValueChangeListener is not required any more.

Other XPages (actually, JSF) constructs have different lifetimes. None are stored in scopes, because they are not set as Serializable. They exist in the faces-config only to provide mappings to the underlying Java class. So converters and validators, for example, are called as and when the XPages code encounters the converter-id variable, for example. Some like VariableResolvers, PropertyResolvers, PhaseListeners and ViewHandlers are used on every request. Any in your NSF are triggered, along with any in extension libraries, as well as the core XPages runtime version. This is why code in those classes needs to be optimised as much as possible, or the impacts upon an application can become greater.

1 thought on “Managed Beans, Scopes and Lifetimes”

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top