Proposal for 3.0 alignment with JSF 2.2: Scope management in support of
@PreDestroy annotation
----------------------------------------------------------------------------------------------
Key: PORTLETBRIDGE-200
URL: https://issues.apache.org/jira/browse/PORTLETBRIDGE-200
Project: MyFaces Portlet Bridge
Issue Type: New Feature
Components: General
Affects Versions: 3.0.0
Reporter: Neil Griffin
Assignee: Michael Freedman
Section 6.8.1 of the Spec discusses the need for the @BridgePreDestroy
annotation. Here's the background for the requirement...
Let's start by looking at the JavaDoc comments for the following methods on the
JSF ExternalContext class:
http://javaserverfaces.java.net/nonav/docs/2.0/javadocs/javax/faces/context/ExternalContext.html#getApplicationMap()
http://javaserverfaces.java.net/nonav/docs/2.0/javadocs/javax/faces/context/ExternalContext.html#getRequestMap()
http://javaserverfaces.java.net/nonav/docs/2.0/javadocs/javax/faces/context/ExternalContext.html#getSessionMap()
The design here seems good, in that it is servlet/portlet agnostic: The JSF API
makes it clear that it is the responsibility of the underlying java.util.Map to
invoke methods annotated with javax.annotation.PreDestroy when attributes are
removed from the Map.
But here is the problem: The Mojarra and MyFaces JSF implementations don't have
this logic in their Map implementations. Instead, they that they rely on the
underlying Servlet Container (i.e. Tomcat) to call the listeners when
attributes are added/removed. See:
http://download.oracle.com/javaee/6/api/javax/servlet/ServletContextAttributeListener.html
Mojarra: The class named ConfigureListener implements the
javax.servlet.ServletContextAttributeListener interface:
http://java.net/projects/mojarra/sources/svn/content/trunk/jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java?rev=8946
MyFaces: The class named ManagedBeanDestroyerListener implements the
javax.servlet.ServletContextAttributeListener interface:
http://svn.apache.org/repos/asf/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/ManagedBeanDestroyerListener.java
To further explain the problem... Portlet Containers typically implement the
javax.portlet.PortletRequest as a layer of abstraction on top of an underlying
javax.servlet.http.HttpServletRequest. However, often times that underlying
HttpServletRequest is issued against a webapp context other than that of the
portlet. In the case of the typical Portal+Tomcat bundle, the browser issues an
HTTP-GET request to the tomcat/webapps/ROOT context. If the JSF implementation
(Mojarra or MyFaces) where present in the tomcat/webapps/ROOT context, then
their ServletContextAttributeListeners would get invoked. But that's not where
the JSF implementation typically lives -- instead, it lives in a different
context like tomcat/webapps/my-jsf-portlet. So that means in a (local) portal
environment, the ServletContextAttributeListeners do not get invoked.
What's further complicates things... There are two different kinds of portals:
Local (like Liferay) and Remote (like Oracle WebCenter). Local Portals invoke
portlets that are running within the same servlet container. Remote Portals
invoke portlets that are running elsewhere via WSRP. As I stated earlier, in
the case of Local Portals, the Mojarra and MyFaces
ServletContextAttributeListeners don't get invoked in other contexts. BUT in
the Remote Portal WSRP scenario, the Mojarra and MyFaces
ServletContextAttributeListeners DO INDEED get invoked.
Finally, the last component of the problem is that the JSF API doesn't really
address the whole idea of scope management, such as listening to when a scope
comes to an end. That's left as an implementation detail, and the bridge
basically is left in the dark as to when underlying map entries are supposed to
go out-of-scope, and also has no idea which entries in the map are managed
beans, unless they are annotated with the @ManagedBean annotation.
So that's why Section 6.8.1 introduces the @BridgePreDestroy annotation. In a
portlet environment, Mojarra/MyFaces cannot be relied upon to invoke methods
annotated with plain old @PreDestroy. They might, or they might not. So in
order to have a reliable mechanism for a "pre destroy" type of annotated method
in a portlet environment, the Bridge provides the @BridgePreDestroy annotation.
It is guaranteed to always work in a portlet environment.
So this issue serves as a proposal to align with the JSF 2.2 EG in order to
fortify the JSF API with scope management (or scope listening) features. This
would also enable us to deprecate the @BridgePreDestroy feature. Bear in mind
that CDI comes into play here as well. Whatever we do, we want to play nicely
with CDI when it is present in the portlet application.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira