Uploaded image for project: 'PUBLIC - Liferay Faces'
  1. PUBLIC - Liferay Faces
  2. FACES-1470

Memory leak for RequestScoped, SessionScoped, and ViewScoped managed-beans when running under Mojarra + JBoss AS

    Details

      Description

      Mojarra has a vendor-specific Service Provider Interface named com.sun.faces.spi.InjectionProvider that is designed as an extension point for Servlet Container / Application Servers to handle dependency injection and cleanup of beans that are managed by the JSF Managed Bean Facility.

      The JBoss implementation if InjectionProvider is named org.jboss.as.web.deployment.jsf.JsfInjectionProvider and is bundled with JBoss AS. When Mojarra calls InjectionProvider.inject(Object managedBean) for beans annotated with @ManagedProperty, the JBoss JsfInjectionProvider will cause JBoss AS to hold onto a reference to the managedBean. If the InjectionProvider.invokePredestroy(Object managedBean} is not called, then JBoss AS experiences a memory leak.

      For @RequestScoped managed-beans running locally (not with WSRP), JBoss AS experiences a memory leak. Since the underlying HttpServletRequest occurs for the portal webapp context (ROOT), the JSF portlet request attributes are not associated with the portlet webapp context. Therefore, the Mojarra com.sun.faces.application.WebappLifecycleListener.attributeRemoved(ServletRequestAttributeEvent) method is never called in a local portlet environment. The solution to this problem is to have the portlet bridge discover the InjectionProvider instance and invoke the InjectionProvider.invokePredestroy(Object managedBean} method via reflection.

      For @SessionScoped managed-beans, JBoss AS also experiences a memory leak during session expiration. When Mojarra creates a @SessionScoped managed-bean during the JSF lifecycle, it calls ExternalContext.getSessionMap().put(String name, Object value) which causes the portlet bridge to store the bean via PortletSession.setAttribute(String, name, Object value). Section PLT.18.3 of the Portlet 2.0 Specification titled "Binding Attributes into a Session" requires that PortletSession attribute names be namespaced/prefixed with the "javax.portlet.p.<ID>?" pattern when they are stored in the underlying HttpSession. This means that the Mojarra com.sun.faces.application.WebappLifecycleListener.attributeRemoved(HttpSessionBindingEvent) method is unable to determine if session attributes are managed-beans, because the com.sun.faces.mgbean.BeanManager.isManaged(String) method returns false. Again, the solution to this problem is to have the portlet bridge discover the InjectionProvider instance and invoke the InjectionProvider.invokePredestroy(Object managedBean) method via reflection.

      For @ViewScoped managed-beans, JBoss AS also experiences a memory leak during session expiration. This is because the Mojarra com.sun.faces.application.view.ViewScopeManager is unable to get the value of the "com.sun.faces.application.view.activeViewMaps" session attribute since the attribute name is namespaced/prefixed with the "javax.portlet.p.<ID>?" pattern, and therefore is unable to cleanup the managed-beans in the view map. The solution to this problem is to have the portlet bridge remove the "javax.portlet.p.<ID>?" prefix from session attribute names and then call the ViewScopeManager.sessionDestroyed(HttpSessionEvent) method via reflection. NOTE THAT THE FIX WILL ONLY WORK WITH Mojarra 2.1.18 (OR NEWER) since the ViewScopeManager was introduced in JAVASERVERFACES-2688.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              neil.griffin Neil Griffin
              Reporter:
              neil.griffin Neil Griffin
              Participants of an Issue:
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Packages

                  Version Package
                  liferay-faces-2.1.2-ga3
                  liferay-faces-3.0.2-legacy-ga3
                  liferay-faces-3.0.2-ga3
                  liferay-faces-3.1.2-ga3