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

Disable initialization of namespaced PortletContext attributes in GenericFacesPortlet.init(PortletConfig) by default

    Details

      Description

      Legacy Requirements as Specified

      Section 4.1 of the JSR 301/329 Specification titled "Configuration" states:

      ... the GenericFacesPortlet reads the following portlet initialization parameters and either sets the appropriate context attributes to direct the bridge's execution or uses it to impact its own behavior:

      javax.portlet.faces.defaultViewId.[mode]*
      javax.portlet.faces.excludedRequestAttributes*
      javax.portlet.faces.preserveActionParams*
      javax.portlet.faces.bridgeEventHandler*
      javax.portlet.faces.bridgePublicRenderParameterHandler*
      javax.portlet.faces.autoDispatchEvents**
      javax.portlet.faces.defaultRenderKitId*
      

      * indicates a parameter that affects bridge execution
      ** indicates a parameter that only affects GenericFacesPortlet execution

      In addition, Section 4.2 of the Specification titled "Structure" states:

      The GenericFacesPortlet subclasses javax.portlet.GenericPortlet. It overrides the init, destroy, doDispatch, doEdit, doHelp, doView, processAction, and renderHeaders methods. In addition it defines the following new methods:

      getBridgeClassName
      getDefaultViewIdMap*
      getExcludedRequestAttributes*
      isPreserveActionParameters*
      getResponseContentType
      getResponseCharacterSetEncoding
      getBridgeEventHandler*
      getBridgePublicRenderParameterHandler*
      isAutoDispatchEvents*
      getFacesBridge
      

      * indicates a method that corresponds to one of the aforementioned parameters that affect bridge execution

      Legacy Requirements Implications

      Because of these requirements, WEB-INF/portlet.xml init-param values (stored in PortletConfig) are saved/cached as namespaced PortletContext attributes (not PortletContext parameters) with the following naming format:

      javax.portlet.faces.<portlet-name>.bridgeEventHandler
      javax.portlet.faces.<portlet-name>.bridgePublicRenderParameterHandler
      javax.portlet.faces.<portlet-name>.defaultRenderKitId
      javax.portlet.faces.<portlet-name>.defaultViewIdMap
      javax.portlet.faces.<portlet-name>.excludedRequestAttributes
      javax.portlet.faces.<portlet-name>.preserveActionParams
      

      Legacy Requirements Benefits & Drawbacks

      There are benefits and drawbacks to these requirements:

      Benefits:

      • The "javax.portlet.faces" (standards based) init-param values listed in Section 4.1 are read and processed once at initialization time, providing a potential performance enhancement, however some of these could instead be done in the Bridge.init(PortletConfig) implementation.
      • The developer can @Override methods listed in Section 4.2 in order to change default behavior, but is probably very very rarely used since most JSF portlets are able to use GenericFacesPortlet without subclassing it.

      Drawbacks:

      • Each time the EG wants to add a new "javax.portlet.faces" (standards based) init-param feature, it involves:
        • Adding a new constant to Bridge.java
        • Adding a corresponding method to GenericFacesPortlet.java
        • Ensuring that GenericFacesPortlet.java calls the corresponding method and caches the value as a namespaced PortletContext attribute.
      • The JSR 378 BridgePortletConfigFactory (see ---FACES-2685---) is unable to decorate these init-param values, because GenericFacesPortlet.init(PortletConfig) cannot assume that the portlet container implementation will complete sending servlet context initialization events prior to calling Portlet.init(PortletConfig). In terms of the Mojarra implementation of JSF, GenericFacesPortlet cannot assume that the Mojarra ConfigureListener will execute and fire javax.faces.event.PostConstructApplicationEvent before the portlet is initialized. The result is that GenericFacesPortlet cannot assume that any of the bridge's factories (such as the BridgePortletConfigFactory) have been initialized by scanning META-INF/faces-config.xml descriptors for factory extensions.
      • The getBridgeEventHandler() and getBridgePublicRenderParameterHandler() methods utilize Java's Thread Context Class Loader (TCCL) in the API jar module, which can cause classpath problems an an OSGi environment, or an application server that deploys API jars as OSGi modules.
      • In order for getBridgeEventHandler() to utilize the BridgeEventHandlerFactory and getBridgePublicRenderParameterHandler() to utilize the BridgePublicRenderParameterHandlerFactory (see FACES-2778) the API has to create an instance of a BridgeEventHandler / BridgePublicRenderParameterHandler that defers actual factory lookup until the first request, but utilizing a thread-safe double-check idom.

      Proposal

      This issue serves as a proposal for:

      1. Deprecating the following constants in javax.portlet.faces.Bridge:

      Bridge.java
      public static final String BRIDGE_EVENT_HANDLER = "bridgeEventHandler";
      public static final String BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER = "bridgePublicRenderParameterHandler";
      public static final String DEFAULT_RENDERKIT_ID = "defaultRenderKitId";
      public static final String DEFAULT_VIEWID_MAP = "defaultViewIdMap";
      public static final String EXCLUDED_REQUEST_ATTRIBUTES = "excludedRequestAttributes";
      public static final String PRESERVE_ACTION_PARAMS = "preserveActionParams";
      

      2. Deprecating the corresponding methods in javax.portlet.faces.GenericFacesPortlet:

      GenericFacesPortlet.java
      public BridgeEventHandler getBridgeEventHandler() throws PortletException
      public BridgePublicRenderParameterHandler getBridgePublicRenderParameterHandler() throws PortletException
      public String getDefaultRenderKitId()
      public Map<String, String> getDefaultViewIdMap()
      public List<String> getExcludedRequestAttributes()
      public boolean isPreserveActionParameters()
      

      3. Preventing GenericFacesPortlet.init(PortletConfig) from calling the methods listed in #2, which would in turn prevent the following PortletContext attributes from being set at initialization time:

      javax.portlet.faces.<portlet-name>.bridgeEventHandler
      javax.portlet.faces.<portlet-name>.bridgePublicRenderParameterHandler
      javax.portlet.faces.<portlet-name>.defaultRenderKitId
      javax.portlet.faces.<portlet-name>.defaultViewIdMap
      javax.portlet.faces.<portlet-name>.excludedRequestAttributes
      javax.portlet.faces.<portlet-name>.preserveActionParams
      

      4. Introducing the following constant in GenericFacesPortlet.java, which is a portlet initialization parameter (default is false) that when set to true in portlet.xml, would cause GenericFacesPortlet.init(PortletConfig) to work as designed in JSR 301/329.

      GenericFacesPortlet.java
      public static final String INITIALIZE_NAMESPACED_CONTEXT_ATTRIBUTES =
      	"javax.portlet.faces.initializeNamespacedContextAttributes";
      

      5. Handling this functionality in the implementation, following the basic principle that less code in the API is more desirable than more code in the API.

      Closely Related Issue

      This issue is closely related to FACES-3098 which, if standardized would cause ExternalContext.getInitParameter(String) and ExternalContext.getInitParameterMap() first check PortletConfig.getInitParameter(String) before calling PortletContext.getInitParameter(String).

        Attachments

          Activity

            People

            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Packages

                Version Package
                facesbridge-api-5.0.0
                facesbridge-tck-5.0.0
                facesbridge-spec-5.0.0
                bridge-impl-3.1.0
                bridge-impl-4.1.0
                bridge-api-3.1.0
                bridge-api-4.1.0