Version: 6.0.0-SNAPSHOT
The majority of the Bridge's control function is implemented by overriding various Faces extension points to translate between the corresponding Faces function and the Portlet model.
The Faces ExternalContext
provides the container independent abstraction of the request and response to the Faces
runtime environment. By implementing an ExternalContext
, the portlet bridge provides access to the portlet request and
response.
The ExternalContext
is acquired from the FacesContext
. To provide an ExternalContext
implementation, the bridge
must provide a FacesContext
implementation. A FacesContext
is manufactured via a FacesContextFactory [Section 6.5 of
JSF 1.2 Specification]. The bridge must use the Faces FactoryFinder
to acquire the FacesContextFactory
which it then
uses to instantiate and acquire a FacesContext
.
The bridge provides an implementation of FacesContextFactory
in order to expose its ExternalContext
. This
FacesContextFactory
must be configured as a service provider in the META-INF/services
directory of the Java jar file
containing the bridge implementation:
The file META-INF/services/javax.faces.context.FacesContextFactory
contains the name of the bridge's concrete
FacesContextFactory
implementation class[6.1].
The bridge's implementation of the FacesContextFactory
must follow the decorator design pattern such that there is a
constructor with a single argument of type FacesContextFactory
so that the custom implementation receives a reference
to the implementation that was previously fulfilling the role. In this way, the custom implementation is able to
override just a subset of the functionality (or provide only some additional functionality) and delegate the rest to the
existing implementation.
In implementing the getFacesContext
method, the bridge must provide its own instance of the FacesContext
without
delegating if and only if the request is being serviced by a portlet in the portlet container. Otherwise the bridge must
delegate to the previous factory and perform no other action.
The bridge must not assume that the FacesContext
returned by calling getFacesContext
is an instanceof its
FacesContext
implementation class[6.2]. Other Faces subsystems running in the portlet
bridge environment are free to introduce their own factory and wrapping implementation as long as they follow the
decorator pattern described above.
FacesContext
contains all of the per-request state information related to the processing of a single Faces request and
the rendering of the corresponding response. It is passed to, and potentially modified by, each phase of the request
processing lifecycle.
A FacesContext
instance is associated with a particular request at the beginning of request processing, by a call to
the getFacesContext()
method of the FacesContextFactory
instance associated with the current web application. 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[nt].
Because there are subtle differences between the servlet and portlet models, its recommended that the bridge's
FacesContext
implementation not delegate any method implementations. For each method implemented by the bridge's
FacesContext
, the implementation must meet all the requirements for that method as defined in the JSF 1.2
specification.
In addition, the bridge's FacesContext
is required to do the following:
setViewRoot()
:
If the class of the UIViewRoot
passed to setViewRoot
is annotated with
javax.portlet.faces.annotation.PortletNamingContainer
then it additionally must set the
"X-JAVAX-PORTLET-FACES-NAMESPACED-RESPONSE"
portlet response property with a String value of "true"
. For further
explanation see section 6.6.
The Faces 1.2 ExternalContext
javadoc describes specific behaviors for each method executed in the portlet request
context. By and large these descriptions are complete and accurate. Section
6.1.3.2 provides these descriptions. However, a few methods aren't adequately
described or are incorrect. For these the bridge must ignore the existing javadoc and implement the behavior as
described in the next section 6.1.3.1.
The Faces 1.2 API defined two types of URLs that could be rendered to the response: action and resource. It also established a 1::1 correspondence between "getting" a URL from the view handler and "encoding" a URL via external context.
The ViewHandler.getActionURL(FacesContext facesContext,String
viewId)
method was designed to return a URL "suitable for rendering" that "selects the specified view identifier" but does not
encode the URL in any specific way. Instead, it is the responsibility of the caller to subsequently call
ExternalContext.encodeActionURL(String)
in order to obtain an encoded URL that can be written to the response. For example, Mojarra's
com.sun.faces.renderkit.html_basic.FormRenderer
class follows this convention when writing the "action"
attribute of a <form>
element.
Similarly, the ViewHandler.getResourceURL(FacesContext facesContext, String
path)
method was designed to return a URL "suitable for rendering" that "selects the specified web application resource" but
does not encode the URL in any specific way. Instead, it is the responsibility of the caller to subsequently call
ExternalContext.encodeResourceURL(String)
in order to obtain an encoded URL that can be written to the response. For example, Mojarra's
com.sun.faces.renderkit.html_basic.ImageRenderer
class follows this convention when writing the "src"
attribute of an <img>
element.
Upon closer examination of the Faces 1.2 JavaDoc for ExternalContext.encodeActionURL(String url)
and
ExternalContext.encodeResourceURL(String url)
, the following requirements are common to both:
Servlet: This must be the value returned by javax.servlet.http.HttpServletResponse.encodeURL(String url).
Portlet: This must be the value returned by javax.portlet.PortletResponse.encodeURL(String url).
The requirement for the "Servlet" use-case is correct, but as section 6.1.3.1
explains, the requirement for the "Portlet" use-case is not adequately described in that it does not take into account
all the features of the FacesBridge. Regardless, the Faces 1.2 JavaDoc reveals that the original intent for these
methods was to be a simple layer of abstraction to encode/rewrite URLs (such as calling
HttpServletResponse.encodeURL(String)
in order to append the jessionid
URL parameter when the user-agent does not
support cookies). Further developed in the next section, this original intent helps to explain why Faces 2.0
requires "bookmarkable" and "redirect" URLs to be encoded by calling ExternalContext.encodeActionURL(String url)
before being written to the response.
The Faces 2.0 API added two additional methods for getting URLs from the view handler:
ViewHandler.getBookmarkableURL(FacesContext facesContext, String viewId, Map<String,List<String>> parameters, boolean
includeViewParams)
and ViewHandler.getRedirectURL(FacesContext facesContext, String viewId, Map<String,List<String>> parameters, boolean
includeViewParams).
However, the Faces 2.0 API did not add two new types of URLs. Rather, both "bookmarkable" and "redirect" URLs are
simply considered to be Faces action URLs (i.e. they target a Faces view). Because of this, both "bookmarkable" and
"redirect" URLs must ultimately be encoded by calling ExternalContext.encodeActionURL(String)
before they are
written to the response.
The Faces 2.0 API maintained the 1::1 correspondence between view handler URL methods and external context URL methods
by introducing ExternalContext.encodeBookmarkableURL(String
url)
and ExternalContext.encodeRedirectURL(String
url).
However, the implementation requirements departed from the pattern of having the caller of the view handler methods
to be responsible for calling the corresponding external context methods. Instead, ViewHandler.getBookmarkableURL(...)
would itself be required to first call ExternalContext.encodeBookmarkableURL(String url)
and pass the result to
ExternalContext.encodeActionURL(String url)
before returning the value. Similarly, ViewHandler.getRedirectURL(...)
would itself be required to first call ExternalContext.encodeRedirectURL(String url)
and pass the result to
ExternalContext.encodeActionURL(String url)
before returning the value. As a consequence of this,
ViewHandler.getBookmarkableURL(...)
and ViewHandler.getRedirectURL(...)
both return fully encoded URLs that can be
written to the response. For example, Mojarra's
com.sun.faces.renderkit.html_basic.OutcomeTargetRenderer
assumes that the return value of ViewHandler.getBookmarkableURL(...)
can be written directly to the response.
In order to facilitate Ajax, the Faces 2.0 API introduced a new type of URL called the partial action URL.
However, the Faces 2.0 view handler API does not contain a "getPartialActionURL" method. Instead, the value returned by
the ViewHandler.getActionURL(FacesContext facesContext, String viewId)
method is to be passed to the
ExternalContext.encodePartialActionURL(String
url)
method before it can be written to the response. This departs from the pattern of 1::1 correspondence between
URL methods in view handler and external context.
The following methods require an implementation that aren't adequately described in the Faces 1.2 ExternalContext
javadoc:
-
dispatch()
:Dispatch a request to the specified resource to create output for this response. This must be accomplished by calling the
javax.portlet.PortletContext
methodgetRequestDispatcher()
, and calling theforward()
[6.3] method on the resulting object unlessdispatch()
has already been called (at least once) within this portlet request. Ifdispatch()
has already been called within this portlet request, theninclude()
may be called rather thanforward()
. This situation might occur in a bridge that doesn't wrap the response prior to dispatch with a wrapper that prevents committing the response which happens implicitly at the completion of the forward processing.Note: Because the Portlet 1.0 bridge was restricted to using
include()
, rendering may appear differently when *the application runs in a 1.0 vs. a 2.0 bridge. Specifically, in a Portlet 2.0 bridge any markup written prior to *callingdispatch
will not be returned to the client, while it will in a Portlet 1.0 bridge environment. For *(potential) backwards compatibility a bridge may provide an implementation specific mechanism to be configured to *support portlet 1.0 bridge dispatch behavior (only useinclude
) as long as this is not the default behavior. -
encodeActionURL()
:Process the
inputURL
and construct and encode a corresponding valid portlet (generally action) URL. If called during theHEADER_PHASE
orRESOURCE_PHASE
, return this URL so it can be written into the markup response. If called during theACTION_PHASE
, directly encode this URL in the action response. The value and form of the URL returned when running in theACTION_PHASE
is undefined although it must not benull
. If called during theEVENT_PHASE
, directly encode this URL in the event response. The value and form of the URL returned when running in theEVENT_PHASE
isundefined although it must not benull
.To process such an
inputURL
correctly, this method must:- If the
inputURL
starts with the # character[6.4] or theinputURL
is an absolute path external to this portlet application[6.5] return theinputURL
unchanged. - If the
inputURL
contains the parameterjavax.portlet.faces.DirectLink
(with a value of "true") return an absolute path derived from theinputURL
. Don't remove theDirectLink
parameter if it exists[6.6]. If theinputURL
contains the parameterjavax.portlet.faces.DirectLink
and its value is false then remove thejavax.portlet.faces.DirectLink
parameter and its value from the query string and continue processing (using the next step concerning determining the target of theURL
)[6.7]. - If the client window feature is enabled and the URI does not have a
ResponseStateManager.CLIENT_WINDOW_URL_PARAM
parameter, then set the parameter on the URI with the value returned byjavax.faces.lifecycle.ClientWindow#getId()
as well as any associated parameters returned byjavax.faces.lifecycle.ClientWindow.getQueryURLParameters(FacesContext)
[6.10]. - Determine the target of the
URL
:- If the
inputURL
starts with the URI scheme"portlet:"
the target is the portlet itself. Interpret thisinputURL
as follows:- The scheme "
portlet:
" indicates that the target of this action is the portlet itself. Though generally used to generate links to non-Faces views in this portlet it can also be used to generate action or render links to a Faces view (including the current view). - The scheme is followed by either the keyword
action
,render
orresource
.render
indicates a portletrenderURL
should be encoded[6.8].action
indicates a portletactionURL
should be encoded[6.9].resource
indicates a portletresourceURL
should be encoded[6.102]. - Following this URL type indicator is an optional query string. Parameter value pairs in the query string
are the parameters that are to be encoded into the
portletURL
.
To generate a link to a Faces view, encode the view as the value of either the `_jsfBridgeViewId` or `_jsfBridgeViewPath` parameter (depending on whether you are encoding the viewId or the viewPath). Targets of such references are run in new empty scopes. An exception is made when the target is the current view and either of the above parameters is included in the query string with a value of `_jsfBridgeCurrentView`. In this case the URL is encoded with the current render parameters and hence retains access to its state/scope. In all cases the bridge removes the above parameter(s) from the query string before generating the encoded URL.
For a resource URL, a Faces view is only encoded if one of the `_jsfBridgeViewId` or `_jsfBridgeViewPath` parameters is included in the query string, otherwise a non-Faces resource URL is generated. The `_jsfBridgeCurrentView` value is used as a shortcut to indicate the resource targets the current view.
A simplified BNF is:
`portletURL = Scheme URLType [QueryString]`
`Scheme = "portlet:"`
`URLType = ("action" | "render" | "resource")`
`QueryString = "?" ParameterPair {"&" ParameterPair}`
`ParameterPair = Text "=" Text`
- The scheme "
- If the
inputURL
contains a full or relative path then analyze the path information to determine whether it encodes a request to a Faces view or a non-Faces view. If it is a reference to a Faces view the target is the encoded Faces viewId[6.10, 6.18]. If it is a reference to a non-Faces view, the target is the path that follows the context path (or if relative, constructed relative to the current view path).- To determine if the
URL
represents a Faces request, determine if the servlet container would map this URL to the Faces servlet. This can be done by reading the servlet definitions in the web application'sweb.xml
to determine how the Faces servlet is mapped and then checking theURL
to see if it would be mapped. If a FacesURL
, derive the view identifier encoded in thisURL
, as follows: (Note: all resultingviewIds
start with a "/")- If prefix mapping (such as "/faces/*") is used for the
FacesServlet
, theviewId
is set from the extra path information of the requestURI
. This corresponds to the path that follows the prefix mapping. e.g. a prefix mapped URL such as /faces/mypage.jsp would have aviewId
of "/mypage.jsp". - If suffix mapping (such as "*.faces") is used for
FacesServlet
, theviewId
is set from the servlet path information of the request URI, after replacing the suffix with the value of the context initialization parameter named by the symbolic constantViewHandler.DEFAULT_SUFFIX_PARAM_NAME
(if no such context initialization parameter is present, use the value of the symbolic constantViewHandler.DEFAULT_SUFFIX
as the replacement suffix). This corresponds to the path that follows the context path. e.g. a suffix mapped URL such as /pages/secondpage.jsf would have aviewId
of "/pages/secondpage.jsp" (assuming .jsp is the replacement suffix).
- If prefix mapping (such as "/faces/*") is used for the
- To determine if the
- If the
- Process PortletURL related state modifications.
- The portlet model allows one to encode changes to the portlet's mode, window state and or security (access)
level in self-referencing URLs or as a response to an action request. Because the form of this encoding is not
specified by the portlet standard these values aren't manipulated in the portlet URL's query string. Rather
changes are expressed by operating directly on a
PortletURL
object (header phase) or theactionResponse
(action phase). AsencodeActionURL()
isolates Faces clients from these APIs/objects, an alternative technique is provided soencodeActionURL()
can recognize and incorporate the necessary changes. This technique recognizes special query string parameters in theinputURL
which are extracted and processed using the corresponding APIs. encodeActionURL() processing must:- recognize the query string parameter
javax.portlet.faces.PortletMode
and use the value of this parameter to identify the mode that should be encoded in the generated reference[6.11, 6.19]. If the value doesn't identify a valid mode then no encoding action is taken[6.12, 6.19]. Regardless of validity, it must also prevent this query string parameter from being carried forward directly in the generated reference. - recognize the query string parameter
javax.portlet.faces.WindowState
and use the value of this parameter to identify the window state that should be encoded in the generated reference[6.13, 6.21]. If the value doesn't identify a valid window state then no encoding action is taken[6.14, 6.22]. Regardless of validity, it must also prevent this query string parameter from being carried forward directly in the generated reference. - recognize the query string parameter
javax.portlet.faces.Secure
and use the value of this parameter to identify the security level that should be encoded in the generated reference[6.15, 6.23]. A value of true or false is translated into the boolean true/false respectively regardless of case. Any other value is ignored[6.16, 6.24]. Regardless of validity, it must also prevent this query string parameter from being carried forward directly in the generated reference. - All other query string parameters are added to the PortletURL as parameters[6.17, 6.25].
- recognize the query string parameter
- The portlet model allows one to encode changes to the portlet's mode, window state and or security (access)
level in self-referencing URLs or as a response to an action request. Because the form of this encoding is not
specified by the portlet standard these values aren't manipulated in the portlet URL's query string. Rather
changes are expressed by operating directly on a
- Perform the encoding:
- If executed during the
ACTION_PHASE
encode into theActionResponse
and return a non-nullURL
as follows[6.10-6.17]:- the target, if the target is not the portlet itself (as identified by use of the
portlet: URI
). When the target is a FacesviewId
, it is encoded in an implementation dependent manner. When the target is a non-Faces view, the target is encoded as the value of the parameter named_jsfBridgeNonFacesView
. - the identified state modifications
- any additional query string parameters that were in the
inputURL
.
- the target, if the target is not the portlet itself (as identified by use of the
- If executed during the
EVENT_PHASE
encode into theEventResponse
and return a non-nullURL
as follows[6.103-6.110]:- the target (see action description)
- the identified state modifications
- any additional query string parameters that were in the
inputURL
.
- If executed during the
HEADER_PHASE
orRESOURCE_PHASE
and the target was determined by URL path (not portlet: syntax) and that target is a Faces viewId, construct and return anactionURL
by callinggetResponse().createActionURL().toString()
as follows[6.18-6.25, 6.111-6.118]:- encode the target determined above (in an implementation dependent manner).
- the identified state modifications,
- any additional query string parameters that were in the
inputURL
.
- If executed during the
HEADER_PHASE
orRESOURCE_PHASE
and the target was determined by its URL path (not portlet: syntax) and that target is a non-FacesviewId
, construct and return arenderURL
by callinggetResponse().createRenderURL().toString()
as follows[6.136-6.152]:- encode the target determined above as the value of the parameter named
_jsfBridgeNonFacesView
. - the identified state modifications.
- any additional query string parameters that were in the
inputURL
.
- encode the target determined above as the value of the parameter named
- If executed during the
HEADER_PHASE
orRESOURCE_PHASE
and the target was determined from the portlet: syntax (not by path), construct the appropriateURL
type determined from the path portion of the based on theurlTypeInputURL
and return its value inString
form (usingtoString()
) as follows:- encode the identified state modifications.
- any additional query string parameters that were in the
inputURL
. - if the target of this URL is the current JSF view as determined by the use of the
_jsfBridgeCurrentView
value, additionally encode all current render parameters into the portletURL. ReturnportletURL.toString()
.
Note on encoding/xml escaping: because renderkits have their own pre/post processing to deal with situations calling for xml escaping in URLs, the bridge must return an URL that contains the identical xml escaping (or not) used in the URL passed to encodeActionURL. I.e. if the incoming URL is xml escaped the returned URL must also be xml escaped, likewise if the incoming URL isn't escaped the returned URL must not be escaped. In the case xml escaping can't be determined from the incoming URL, the bridge must assume the URL is not xml escaped and return an unescaped URL accordingly.[[6.99](tck-tests.md#6.99)] - If executed during the
- If the
-
encodeResourceURL()
:In Portlet 1.0 resources were not served by the portlet but rather accessed directly by the consumer using an http (resource) request. Portlet 2.0 introduces a second type of resourceURL, a (in-protocol) portlet served resource. A resourceURL of this type signifies that the portlet itself should be called by the consumer to generate the resource. The Portlet 2.0 APIs provide distinct calls for creating a reference to portlet served resource to one that is accessed directly. As Faces only has a single concept of a resourceURL, the bridge uses a heuristic to determine which of these two access methods it uses to reference the resource. In summary, resourceURLs that target a Faces view are constructed to be served by the portlet while those that don't target a Faces view are constructed to be accessed directly.
This method returns the inputURL after performing any rewriting needed to ensure that it will correctly identify an addressable resource. To process such an inputURL correctly, this method must:
- If the
inputURL
is opaque, in that it is an absolute URI with a scheme-specific part that doesn't begin with a slash character (e.g.mailto:java-net@java.sun.com
) and the scheme isn't portlet:, return theinputURL
unchanged[6.26]. - If the inputURL 's scheme specific part is portlet: or its not opaque and its query string contains the parameter
javax.portlet.faces.ViewLink with a value equal to true[6.34], then return an URL representing a view navigation.
This is done by:
- if its exists, remove the
javax.portlet.faces.ViewLink
query string parameter. Note: This supports use cases such as using h:outputLink to navigate to a new view. - if it exists, replace the
javax.portlet.faces.BackLink
query string parameter with a parameter whose name is the value of this parameter and whose value is theString
(URL
path) returned after callingViewHandler.getActionURL()
passing the currentviewId
[6.27].
This encodes a "back link" into the resource URL allowing the targeted resource a way back to the calling portlet page for use in the situation where the `resourceURL` actually is used as a page link. E.g. use of `h:outputLink`. - returning the result of calling `encodeActionURL` passing this transformed `inputURL`[[6.33](tck-tests.md#6.33), [6.34](tck-tests.md#6.34)]. - if its exists, remove the
- If the
inputURL
is hierarchical, in that it is either an an absolute URI whose scheme-specific part begins with a slash character, or a relative URI, that is, a URI that does not specify a scheme, and it targets a resource that is external to this application:- check to see if the
inputURL
contains a query string parameter namedjavax.portlet.faces.BackLink
. If it does replace it with a parameter whose name is the value of this parameter and whose value is theString
(URL
path) returned after callingViewHandler.getActionURL()
passing the currentviewId
followed byExternalContext.encodeActionURL()
[6.27].
This encodes a "back link" into the resource `URL` allowing the targeted resource a way back to the calling portlet page for use in the situation where the `resourceURL` actually is used as a page link. E.g. use of `h:outputLink`.
- return `getResponse().encodeURL(inputURL)`[[6.28](tck-tests.md#6.28)]. - check to see if the
- If the
inputURL
is hierarchical and targets a resource that is within this application:- if the
inputURL
is a relativeURL
(i.e. it is neither absolute nor starts with a '/') then theinputURL
must be turned into a context path relative URL by constructing a new URL based on going relative to the current path[6.29]. The current path is defined as the path that would be used todispatch()
to the current view. - ensure that the
inputURL
(potentially modified by the previous step) is a fully qualified pathURI
(i.e. contains the context path)[6.31]. - if the resulting
inputURL
contains a query string parameter namedjavax.portlet.faces.BackLink
then replace it with a parameter whose name is the value of this parameter and whose value is theString
(URL
path) returned after callingViewHandler.getActionURL()
passing the currentviewId
[6.30].
This encodes a "back link" into the resource URL allowing the targeted resource a way back to the calling portlet page. E.g. use ofh:outputLink
. - determine whether the targeted resources will be satisfied using Portlet 2.0 in protocol resource serving
support or Portlet 1.0 out of band http support. The bridge must encode the resource to be satisfied by the in
protocol resource serving support if:
- the query string contains the parameter
javax.portlet.faces.InProtocolResourceLink
- the target is a Faces resource, one that in a servlet environment would be processed running through the
FacesServlet
.
Note: The bridge can choose the strategy for acquiring (representing) all other resources though it is noted that out of band (http) resource access is generally more efficient.
- the query string contains the parameter
- if returning an in protocol resource, return the
String
representation of aresourceURL
created usingresponse.createResourceURL()
after processingPortletURL
related state modifications:- as you can't change a portlet's mode in a resource request, remove and ignore the query string parameter
javax.portlet.faces.PortletMode
if it exists. - as you can't change a portlet's window state in a resource request, remove and ignore the query string
parameter
javax.portlet.faces.WindowState
if it exists. - recognize the query string parameter
javax.portlet.faces.Secure
and use the value of this parameter to identify the security level that should be encoded in the generated reference. A value oftrue
orfalse
is translated into theboolean true/false
respectively regardless of case. Any other value is ignored. Regardless of validity, it must also prevent this query string parameter from being carried forward directly in the generated reference. - All other query string parameters are added to the
ResourceURL
as parameters. - if returning an out of band (http) resource return
getResponse().encodeURL(inputURL)
[6.28].
Note on encoding/xml escaping: because renderkits have their own pre/post processing to deal with situations calling for xml escaping in URLs, the bridge must return an URL that contains the identical xml escaping (or not) used in the URL passed toencodeActionURL
. I.e. if the incoming URL is xml escaped the returned URL must also be xml escaped, likewise if the incoming URL isn't escaped the returned URL must not be escaped. In the case xml escaping can't be determined from the incoming URL, the bridge must assume the URL is not xml escaped and return an unescaped URL accordingly[6.99]. Also, because there are situations where Faces components will further encode returned URL strings by replacing <spaces> in theURL
with the '+' which not all portlet containers may be able to subsequently process, the bridge can (should)URL
-encode the space character (%20) prior to returning theURL
regardless of any stipulation regarding base encoding.
- as you can't change a portlet's mode in a resource request, remove and ignore the query string parameter
- if the
- If the
-
getRequest()
:Return the environment-specific object instance for the current request. This must be the last request object set as a consequence of calling
setRequest()
[6.35] or if none set, the request object passed to this instance's constructor. -
setRequest()
:Set the environment-specific request to be returned by subsequent calls to
getRequest()
[6.35]. This may be used to install a wrapper for the request. -
setRequestCharacterEncoding()
:Overrides the name of the character encoding used in the body of this request[6.37].
Calling this method after reading request parameters or reading input has no effect and throws no exceptions. Calling this method during the RENDER_PHASE is has no effect and throws no exceptions[6.36]. -
getRequestHeaderMap()
:Return an immutable
Map
whose keys are the set of request header names included in the current request, and whose values (of typeString
) are the first (or only) value for each header name returned by the underlying request[6.38, 6.39, 6.119, 6.120]. The returnedMap
must implement the entire contract for an unmodifiableMap
as described in the JavaDocs forjava.util.Map
[6.38, 6.39, 6.119, 6.120]. In addition, key comparisons must be performed in a case insensitive manner.This Map must include the set of properties available via the
javax.portlet.PortletRequest
methodsgetProperty()
andgetPropertyNames()
except when executing aHEADER_REQUEST
or anEVENT_REQUEST
. Within aHEADER_REQUEST
orEVENT_REQUEST
, the map must exclude theContent-Type
andContent-Length
properties (if they are present in the underlying request)[6.38, 6.119].In addition, to provide compatibility with servlets, the bridge must ensure that the following entries exist in the
Map
when the bridge is executing during anACTION_PHASE
orRESOURCE_PHASE
:Accept
,Accept-Language
,Content-Type
, andContent-Length
[6.39, 6.120]. When executing during aHEADER_PHASE
or anEVENT_PHASE
the bridge must only ensure thatAccept
andAccept-Language
exist (and as noted above thatContent-Type
andContent-Length
don't exist)[6.38, 6.119]. The values for these headers are derived as follows:-
Accept
: The value returned for this header must be the result of properly encoding the values returned bygetResponseContentTypes()
as a string conforming to the HTTP 1.1 Accept header format as defined by RFC2616 Section 14.1. -
Accept-Language
: The value returned for this header must be the result of properly encoding the values returned bygetLocales()
as a string conforming to the HTTP 1.1 Accept-Language header format as defined by RFC2616 Section 14.4. -
Content-Type
: The value returned for this header must be the result of properly encoding the values returned bygetContentType()
andgetCharacterEncoding()
as a string conforming to the HTTP 1.1 Content-Type header format as defined by RFC2616 Section 14.17. This header value must only be represented ifgetContentType()
returns a non-null value. The character set portion of this header must only be represented ifgetCharacterEncoding()
returns a non-null value. -
Content-Length
: The value returned for this header must be the result of properly encoding the values returned bygetContentLength()
as a string conforming to the HTTP 1.1 Content-Length header format as defined by RFC2616 Section 14.13. This header value must only be represented ifgetContentLength()
returns a value other then -1.
-
-
getRequestHeaderValuesMap()
:Return an immutable
Map
whose keys are the set of request header names included in the current request, and whose values (of typeString[]
) are all of the value for each header name returned by the underlying request[6.40, 6.41, 6.121, 6.122]. The returnedMap
must implement the entire contract for an unmodifiableMap
as described in the JavaDocs forjava.util.Map
[6.40, 6.41, 6.121, 6.122]. In addition, key comparisons must be performed in a case insensitive manner.This
Map
must include the set of property names and values available via thejavax.portlet.PortletRequest
methodsgetProperty()
andgetPropertyNames()
except when executing aHEADER_REQUEST
or anEVENT_REQUEST
. Within a HEADER_REQUEST,
RENDER_REQUEST, or
EVENT_REQUEST, the map must exclude the
CONTENT-TYPE` property (if it is present in the underlying request)[6.40, 6.121].In addition, to provide compatibility with servlets, the bridge must ensure that the following entries exist in the Map when the bridge is executing during an
ACTION_PHASE
orRESOURCE_PHASE
:Accept
,Accept-Language
,Content-Type
, andContent-Length
[6.41, 6.122]. When executing during aHEADER_PHASE
,RENDER_PHASE
, or anEVENT_PHASE
the bridge must only ensure thatAccept
andAccept-Language
exist (and as noted above thatContent-Type
doesn't exist)[6.40, 6.121]. The values for these headers are derived as follows:-
Accept
: The value returned for this header must be the result of properly encoding the values returned bygetResponseContentTypes()
as a string conforming to the HTTP 1.1 Accept header format as defined by RFC2616 Section 14.1. -
Accept-Language
: The value returned for this header must be the result of properly encoding the values returned bygetLocales()
as a string conforming to the HTTP 1.1 Accept-Language header format as defined by RFC2616 Section 14.4. -
Content-Type
: The value returned for this header must be the result of properly encoding the values returned bygetContentType()
andgetCharacterEncoding()
as a string conforming to the HTTP 1.1 Content-Type header format as defined by RFC2616 Section 14.17. This header value must only be represented ifgetContentType()
returns a non-null value. The character set portion of this header must only be represented ifgetCharacterEncoding()
returns a non-null value. -
Content-Length
: The value returned for this header must be the result of properly encoding the values returned bygetContentLength()
as a string conforming to the HTTP 1.1 Content-Length header format as defined by RFC2616 Section 14.13. This header value must only be represented ifgetContentLength()
returns a value other then -1.
-
-
getRequestMap()
:Return a mutable
Map
representing the request scope attributes for the current application[6.42]. The returnedMap
must implement the entire contract for a modifiable map as described in the JavaDocs forjava.util.Map
. Modifications made in theMap
must cause the corresponding changes in the set of request scope attributes. Particularly theclear()
,remove()
,put()
,putAll()
, andget()
operations must take the appropriate action on the underlying data structure[6.42].For any of the Map methods that cause an element to be removed from the underlying data structure, the following occurs 6.8:
-
If the attribute is excluded from the bridge request scope and the attribute's value is a managed-bean, and it has one or more public no-argument void return methods annotated with
javax.annotation.PreDestroy
, then each such method must be called before the element is removed from the underlying data structure. Elements that are not managed-beans, but do happen to have methods with that annotation must not have those methods called on removal. -
If the attribute is included in the bridge request scope then regardless of whether the attribute is a managed-bean or not, if the attribute's value has one or more public no-argument void return methods annotated with
javax.portlet.faces.annotation.PreDestroy
, then each such method must be called before the element is removed from the underlying data structure[6.42/nt].
Any exception thrown by either of these
PreDestroy
annotated methods must by caught and not rethrown. The exception may be logged.The
Map
must contain the set of attributes available via thejavax.portlet.PortletRequest
methodsgetAttribute()
,getAttributeNames()
,removeAttribute()
, andsetAttribute()
. Furthermore these attributes must be managed across portlet requests according to the rules defined in section 5.1.2[6.43]. -
-
getRequestParameterMap()
:Return an immutable
Map
whose keys are the set of request parameters names included in the current request, and whose values (of typeString
) are the first (or only) value for each parameter name returned by the underlying request[6.45]. The returnedMap
must implement the entire contract for an unmodifiable map as described in the JavaDocs forjava.util.Map
.This
Map
must be composed from the set of parameters available via thejavax.portlet.PortletRequest
methodsgetParameter()
andgetParameterNames()
plus any additional parameter names encoded in the (query string) of theviewId
[6.47]. This later situation primarily occurs when using a defaultviewId
provided by the portlet.In addition, during a portlet's
HEADER_PHASE
, if not otherwise already in theMap
, the bridge must include those parameters managed in the corresponding bridge request scope. This always includes theResponseStateManger.VIEW_STATE_PARAM parameter
[6.45]. The preservation/inclusion of the rest of the action parameters depends on thejavax.portlet.faces.[portlet name].preserveActionParams
portlet context attribute. If this context attribute exists and has a value ofBoolean.TRUE
, the additional action parameters are preserved/included[6.46], otherwise they aren't. -
getRequestParameterNames()
:Return an
Iterator
over the names of all request parameters included in the current request. This must be anIterator
over the values returned by thejavax.portlet.PortletRequest
methodgetParameterNames()
[6.48] plus any additional parameter names encoded in the (query string) of theviewId
[6.50]. This later situation primarily occurs when using a defaultviewId
provided by the portlet.In addition, during a portlet's
HEADER_PHASE
, if not otherwise already in theIterator
, the bridge must include those parameter names managed in the corresponding bridge request scope. This always includes theResponseStateManger.VIEW_STATE_PARAM
parameter[6.48]. The preservation/inclusion of the rest of the action parameters depends on thejavax.portlet.faces.[portlet name].preserveActionParams
portlet context attribute. If this context attribute exists and has a value ofBoolean.TRUE
, the additional action parameters are preserved/included[6.49], otherwise they aren't. -
getRequestParameterValuesMap()
:Return an immutable
Map
whose keys are the set of request parameters names included in the current request, and whose values (of typeString[]
) are all of the values for each parameter name returned by the underlying request[6.51]. The returnedMap
must implement the entire contract for an unmodifiable map as described in the JavaDocs forjava.util.Map
.This must be the set of parameter values available via the
javax.portlet.PortletRequest
methodsgetParameterValues()
andgetParameterNames()
plus any additional parameter names encoded in the (query string) of theviewId
[6.53]. This later situation primarily occurs when using a defaultviewId
provided by the portlet.In addition, during a portlet's
HEADER_PHASE
, if not otherwise already in theMap
, the bridge must include those parameter names managed in the corresponding bridge request scope. This always includes theResponseStateManger.VIEW_STATE_PARAM
parameter[6.51]. The preservation/inclusion of the rest of the action parameters depends on thejavax.portlet.faces.[portlet name].preserveActionParams
portlet context attribute[6.52]. If this context attribute exists and has a value ofBoolean.TRUE
, the additional action parameters are preserved/included, otherwise they aren't. -
getRequestPathInfo()
:Return the extra path information (if any) included in the request
URI
; otherwise, returnnull
. This value must represent the path portion of the current targetviewId
.Because the portlet model doesn't support a (servlet) equivalent notion of
pathInfo
andservletPath
, the bridge must manufacture these values based on the targetviewId
. The bridge determines the target view from request parameter(s) it has previously encoded. If this information doesn't exist, the target view is the defaultviewId
defined by the portlet. The associated pathInfo and servletPath are constructed by determining the servlet mapping of the Faces servlet and constructing the appropriate paths such that they conform to the paths the servlet container generates when processing an http request which targets this view as defined in SRV .3.4 in the Servlet 2.5 specification titled "Request Path Elements"[6.54].Examples:
Faces servlet mapping viewId servletPath pathInfo /faces/* (prefix mapping) myView.jspx /faces myView.jspx *.jsf (suffix mapping) myView.jspx myView.jsf null
-
getRequestServletPath()
:Returns the part of this request's URL that calls the servlet. This path starts with a "/" character and includes either the servlet name or a path to the servlet, but does not include any extra path information or a query string.
This method will return an empty string ("") if the servlet used to process this request was matched using the "/*" pattern.
Because the portlet model doesn't support a (servlet) equivalent notion of
pathInfo
andservletPath
, the bridge must manufacture these values based on the targetviewId
. The bridge determines the target view from request parameter(s) it has previously encoded. If this information doesn't exist, the target view is the defaultviewId
defined by the portlet. The associated pathInfo and servletPath are constructed by determining the servlet mapping of the Faces servlet and constructing the appropriate paths such that they conform to the paths the servlet container generates when processing an http request which targets this view as defined in SRV .3.4 in the Servlet 2.5 specification titled "Request Path Elements"[6.55].Examples:
Faces servlet mapping viewId servletPath pathInfo /faces/* (prefix mapping) myView.jspx /faces myView.jspx *.jsf (suffix mapping) myView.jspx myView.jsf null
-
getRequestCharacterEncoding()
:Return the character encoding currently being used to interpret this request. If called during the
ACTION_PHASE
orRESOURCE_PHASE
, returns the value from the corresponding actionrequest.getCharacterEncoding()
[6.57, 6.123]. If called during the HEADER_PHASEor
EVENT_PHASEit returns
null`[6.56, 6.124]. -
getRequestContentType()
:Return the MIME Content-Type for this request. If called during the
ACTION_PHASE
orRESOURCE_PHASE
, returns the value from the corresponding actionrequest.getContentType()
[6.59, 6.125]. If called during the HEADER_PHASEor
EVENT_PHASEit returns
null`[6.58, 6.126]. -
getResponseCharacterEncoding()
:Returns the name of the character encoding (MIME charset) used for the body sent in this response. If called during the HEADER_PHASE
or
RESOURCE_PHASE, returns the value from the corresponding render
response.getCharacterEncoding()<sup>[[6.60](tck-tests.md#6.60), [6.127](tck-tests.md#6.127)]</sup>. If called during the
ACTION_PHASEor
EVENT_PHASEit throws an
IllegalStateException`[6.61, 6.128]. -
getResponseContentType()
:Return the MIME Content-Type for this response. If called during the HEADER_REQUEST
, or
RESOURCE_PHASE, returns the value from the corresponding
response.getContentType()<sup>[[6.62](tck-tests.md#6.62), [6.129](tck-tests.md#6.129)]</sup>. However, if the return value of the corresponding
response.getContentType()is null, then it returns the value from the corresponding
request.getContentType()<sup>[[5.29](tck-tests.md#5.29)]</sup>. If called during the
ACTION_PHASEor
EVENT_PHASEit throws an
IllegalStateException`[6.63, 6.130]. -
getResponse()
:Return the environment-specific object instance for the current response. This must be the last response object set as a consequence of calling
setResponse()
or if none set, theresponse
object passed to this instance's constructor. -
setResponse()
:Set the environment-specific response to be returned by subsequent calls to
getResponse()
. This may be used to install a wrapper for the response. -
redirect()
:Redirect a request to the specified
URL
.Because the portlet redirect semantics differ from servlets the bridge implements the following support:
-
During an Action Request[6.64]:
- if the redirect target URL starts with '#', references a resource outside of this web application, or contains
the query string parameter
javax.portlet.faces.DirectLink
with a value of "true
", callActionResponse.sendRedirect()
passing theurl
.
This causes the client to redirect from the consumer page to this target.
- otherwise, ensure that the action response is set to cause the subsequent render to target this redirect view. Typically this merely involves ensuring that `encodeActionURL()` has been called on the target.
This is equivalent to a regular faces navigation, the client doesn't redirect, rather the consumer page renders the portlet's new target.
**Note**: in either case, `FacesContext.responseComplete()` must be called before returning. - if the redirect target URL starts with '#', references a resource outside of this web application, or contains
the query string parameter
-
During an Event Request[6.131]:
- if the redirect target URL starts with '#', references a resource outside of this web application, or contains
the query string parameter
javax.portlet.faces.DirectLink
with a value of "true
". The redirect is ignored.
- otherwise, ensure that the event response is set to cause the subsequent render to target this redirect view. Typically this merely involves ensuring that `encodeActionURL()` has been called on the target.
This is equivalent to a regular faces navigation, the client doesn't redirect, rather the consumer page renders the portlet's new target.
**Note**: in either case, `FacesContext.responseComplete()` must be called before returning. - if the redirect target URL starts with '#', references a resource outside of this web application, or contains
the query string parameter
-
During a Header Request:
- if the redirect target URL starts with '#', references a resource outside of this web application, or contains
the query string parameter
javax.portlet.faces.DirectLink
with a value of "true
". The redirect is ignored.
- if the redirect target URL references a non-Faces view then throw an `IllegalStateException`[[6.66](tck-tests.md#6.66)].
- otherwise, call `FacesContext.responseComplete()` to ensure the bridge will cease rendering its current view prior to returning any response content. Instead, capture the markup of the redirect target for rendering during the render phase[[6.65](tck-tests.md#6.65)]. In addition, support this behavior so that subsequent rerenders will ignore the (original) request target and instead render with the (cached) redirect target URL and its preserved saved (render) view state. Special care is needed in managing public render parameters during a render redirect. The bridge must ensure that the public render parameters passed to this request are carried forward and processed during the rendering of the redirect that occurs within the same render request. However, if subsequent rerender (requests), the bridge must not use any of the public render parameters used in the initial render (redirect) but rather use the public render parameters that are reflected in the (new) request. - if the redirect target URL starts with '#', references a resource outside of this web application, or contains
the query string parameter
-
During a Render Request: Write the markup that was captured during the header phase to the response.
-
During a Resource Request[nt]: The redirect is ignored. Take no action.
-
The following methods require an implementation that are adequately described in the Faces 1.2 ExternalContext javadoc.
This includes the implicit requirement that each access to the portlet request
or response
object be done by using
the last request
or response
object set using the corresponding setRequest()
or setResponse()
methods or the
original objects passed to the constructor if none have been directly set.
-
encodeNamespace()
:Return the specified name, after prefixing it with a namespace that ensures that it will be unique within the context of a particular page. The returned value must be the input value prefixed by the value returned by the
javax.portlet.RenderResponse
methodgetNamespace()
[6.67]. -
getApplicationMap()
:Return a mutable
Map
representing the application scope attributes for the current application[6.68]. This must be the set of attributes available via thejavax.portlet.PortletContext
methodsgetAttribute()
,getAttributeNames()
,removeAttribute()
, andsetAttribute()
. The returnedMap
must implement the entire contract for a modifiable map as described in the JavaDocs forjava.util.Map
. Modifications made in theMap
must cause the corresponding changes in the set of application scope attributes. Particularly theclear()
,remove()
,put()
,putAll()
, andget()
operations must take the appropriate action on the underlying data structure.For any of the
Map
methods that cause an element to be removed from the underlying data structure, the following action regarding managed-beans must be taken. If the element to be removed is a managed-bean, and it has one or more public no-argument void return methods annotated withjavax.annotation.PreDestroy
, each such method must be called before the element is removed from the underlying data structure. Elements that are not managed-beans, but do happen to have methods with that annotation must not have those methods called on removal. Any exception thrown by thePreDestroy
annotated methods must by caught and not rethrown. The exception may be logged. -
getAuthType()
:Return the name of the authentication scheme used to authenticate the current user, if any; otherwise, return
null
[6.69]. For standard authentication schemes, the returned value will match one of the following constants:BASIC_AUTH
,CLIENT_CERT_AUTH
,DIGEST_AUTH
, orFORM_AUTH
. This must be the value returned by thejavax.portlet.http.PortletRequest
methodgetAuthType()
. -
getContext()
:Return the application environment object instance for the current application. This must be the current application's
javax.portlet.PortletContext
instance[6.70]. -
getInitParameter()
:Return the value of the specified application initialization parameter (if any). If the result of calling
PortletConfig.getInitParameter(name)
is non-null, then return the non-null value. Otherwise, return the result of callingPortletContext.getInitParameter(String)
[6.71]. -
getInitParameterMap()
:Return an immutable
Map
whose keys are the set of application initialization parameter names configured for this application, and whose values are the corresponding parameter values[6.72]. The returnedMap
must implement the entire contract for an unmodifiable map as described in the JavaDocs forjava.util.Map
. The map keys must be the union of the key names fromPortletConfig.getInitParameterNames()
andPortletContext.getInitParameterNames()
. Each map value must be equal to the non-null result of callingPortletConfig.getInitParameter(name)
. Otherwise, ifPortletConfig.getInitParameter(name)
returns a null value then the map value must be equal to the result of callingPortletContext.getInitParameter(name)
. -
getRemoteUser()
:Return the login name of the user making the current request if any; otherwise, return
null
. This must be the value returned by thejavax.portlet.http.PortletRequest
methodgetRemoteUser()
[6.73]. -
getRequestContextPath()
:Return the portion of the request URI that identifies the web application context for this request. This must be the value returned by the
javax.portlet.PortletRequest
methodgetContextPath()
[6.74]. -
getRequestCookieMap()
:Return an immutable
Map
whose keys are the set of cookie names included in the current request, and whose values (of typejavax.servlet.http.Cookie
) are the first (or only) cookie for each cookie name returned by the underlying request. The returnedMap
must implement the entire contract for an unmodifiable map as described in the JavaDocs forjava.util.Map
.This must be an empty Map[6.75].
-
getRequestLocale()
:Return the preferred
Locale
in which the client will accept content. This must be the value returned by thejavax.portlet.PortletRequest
methodgetLocale()
[6.76]. -
getRequestLocales()
:Return an
Iterator
over the preferredLocale
s specified in the request, in decreasing order of preference. This must be anIterator
over the values returned by thejavax.portlet.PortletRequest
methodgetLocales()
[6.77]. -
getResource()
:Return a
URL
for the application resource mapped to the specified path, if it exists; otherwise, returnnull
. This must be the value returned by thejavax.portlet.PortletContext
methodgetResource(path)
[6.78]. -
getResourceAsStream()
:Return an
InputStream
for an application resource mapped to the specified path, if it exists; otherwise, returnnull
. This must be the value returned by thejavax.portlet.PortletContext
methodgetResourceAsStream(path)
[6.79]. -
getResourcePaths()
:Return the
Set
of resource paths for all application resources whose resource path starts with the specified argument. This must be the value returned by thejavax.portlet.PortletContext
methodgetResourcePaths(path)
[6.80]. -
setResponseCharacterEncoding()
:Sets the character encoding (MIME charset) of the response being sent to the client, for example, to UTF-8. This method must take no action[6.81].
-
getSession()
:If the
create
parameter istrue
, create (if necessary) and return a session instance associated with the current request. If thecreate
parameter isfalse
return any existing session instance associated with the current request, or returnnull
if there is no such session. This method must return the result of callinggetPortletSession(create)
on the underlyingjavax.portlet.PortletRequest
instance[6.82]. -
getSessionMap()
:Return a mutable
Map
representing the session (PORTLET_SCOPE
) scope attributes for the current portlet[6.83]. The returnedMap
must implement the entire contract for a modifiable map as described in the JavaDocs forjava.util.Map
. Modifications made in the Map must cause the corresponding changes in the set of session scope attributes. Particularly theclear()
,remove()
,put()
, andget()
operations must take the appropriate action on the underlying data structure. Accessing attributes via thisMap
must cause the creation of a session associated with the current request, if such a session does not already exist.For any of the
Map
methods that cause an element to be removed from the underlying data structure, the following action regarding managed-beans must be taken. If the element to be removed is a managed-bean, and it has one or more public no-argument void return methods annotated withjavax.annotation.PreDestroy
, each such method must be called before the element is removed from the underlying data structure[6.84]. Elements that are not managed-beans, but do happen to have methods with that annotation must not have those methods called on removal. Any exception thrown by thePreDestroy
annotated methods must by caught and not rethrown. The exception may be logged.This
Map
must be composed from the set of attributes that exist in thePORTLET_SCOPE
available via thejavax.portlet.PortletSession
methodsgetAttribute()
,getAttributeNames()
,removeAttribute()
, andsetAttribute()
. -
getUserPrincipal()
:Return the
Principal
object containing the name of the current authenticated user, if any; otherwise, returnnull
. This must be the value returned by thejavax.portlet.http.PortletRequest
methodgetUserPrincipal()
[6.85]. -
isUserInRole()
:Return
true
if the currently authenticated user is included in the specified role. Otherwise, returnfalse
. This must be the value returned by thejavax.portlet.http.PortletRequest
methodisUserInRole(role)
. -
log()
:Log the specified message to the application object. This must be performed by calling the equivalent form of the
javax.portlet.PortletContext
methodlog()
.
The following methods require an implementation that aren't adequately described in the Faces 2.0 ExternalContext
javadoc:
-
addResponseCookie(String name, String value, Map<String,Object> properties)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than calling
HttpServletResponse.addCookie(Cookie)
, the FacesBridge must callPortletResponse.addCookie(Cookie)
. [6.138]. -
getFlash()
:The FacesBridge is not required to support this method. Due to time constraints, the feature was considered to be out-of-scope for JSR 378. Support has been postponed to a maintenance release or to a subsequent JSR.
-
getMimeType(String)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletContext.getMimeType(String)
the FacesBridge must callPortletContext.getMimeType(String)
. [6.139]. -
getRequestScheme()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletRequest.getScheme()
the FacesBridge must callPortletRequest.getScheme()
. [6.140]. -
getRequestServerName()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletRequest.getServerName()
the FacesBridge must callPortletRequest.getServerName()
. [6.141]. -
getRequestServerPort()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletRequest.getServerPort()
the FacesBridge must callPortletRequest.getServerPort()
. [6.142]. -
getRealPath(String)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletContext.getRealPath(String)
the FacesBridge must callPortletContext.getRealPath(String)
. [6.143]. -
getRequestContentLength()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletRequest.getContentLength()
the FacesBridge must callClientDataRequest.getContentLength()
. [6.144]. -
getResponseOutputStream()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletResponse.getOutputStream()
the FacesBridge must callMimeResponse.getOutputStream()
. It is only valid to call this method during the HEADER_PHASE, RENDER_PHASE, and RESOURCE_PHASE of the portlet lifecycle. No explicit TCK test is necessary, since nearly all tests in the TCK will fail unless this is implemented correctly. -
getResponseOutputWriter()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletResponse.getWriter()
the FacesBridge must callMimeResponse.getWriter()
. It is only valid to call this method during the HEADER_PHASE, RENDER_PHASE, and RESOURCE_PHASE of the portlet lifecycle. No explicit TCK test is necessary, since nearly all tests in the TCK will fail unless this is implemented correctly. -
setResponseContentType(String)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletResponse.setContentType(String)
the FacesBridge must callMimeResponse.setContentType(String)
. It is only valid to call this method during the HEADER_PHASE, RENDER_PHASE, and RESOURCE_PHASE of the portlet lifecycle. [6.145]. -
setResponseContentLength(int)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletResponse.setContentLength(int)
the FacesBridge must callResourceResponse.setContentLength(int)
. It is only valid to call this method during the RESOURCE_PHASE of the portlet lifecycle. [6.146]. -
invalidateSession()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpSession.invalidate()
the FacesBridge must callPortletSession.invalidate()
. [6.147]. -
setResponseHeader(String,String)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpServletResponse.setHeader(String,String)
the FacesBridge must callPortletResponse.setProperty(String,String)
. It is only valid to call this method during the HEADER_PHASE and RESOURCE_PHASE of the portlet lifecycle. [6.148]. -
addResponseHeader(String,String)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpServletResponse.addHeader(String,String)
the FacesBridge must callPortletResponse.addProperty(String,String)
. It is only valid to call this method during the HEADER_PHASE and RESOURCE_PHASE of the portlet lifecycle. [6.149]. -
getResponseBufferSize()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpServletResponse.getBufferSize()
the FacesBridge must callMimeResponse.getBufferSize()
. It is only valid to call this method during the HEADER_PHASE, RENDER_PHASE, and RESOURCE_PHASE of the portlet lifecycle. This method is not testable in a vendor-neutral way since the portlet container implementation has the liberty of making the final decision regarding the size of the buffer, or whether buffering is used at all. -
setResponseBufferSize(int)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpServletResponse.setBufferSize(int)
the FacesBridge must callResourceResponse.setBufferSize(int)
. It is only valid to call this method during the RESOURCE_PHASE of the portlet lifecycle. This method is not testable in a vendor-neutral way since the portlet container implementation has the liberty of making the final decision regarding the size of the buffer, or whether buffering is used at all. -
isResponseCommitted()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpServletResponse.isCommitted()
the FacesBridge must callMimeResponse.isCommitted()
. It is only valid to call this method during the HEADER_PHASE, RENDER_PHASE, and RESOURCE_PHASE of the portlet lifecycle. TCK: This method is not testable by the Selenium-based TCK since there is no way to write to the response ifMimeResponse.isCommitted()
returnstrue
. -
responseReset()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpServletResponse.reset()
the FacesBridge must callMimeResponse.reset()
. It is only valid to call this method during the HEADER_PHASE, RENDER_PHASE, and RESOURCE_PHASE of the portlet lifecycle. [6.150] -
responseSendError(int,String)
:The FacesBridge is unable to comply with the requirements specified in the JSF 2.2 JavaDoc because the Portlet 3.0 API does not have an equivalent to
HttpServletResponse.sendError(int,String)
. Instead, this method must call through to theExternalContext.setResponseStatus(int)
method. It is only valid to call this method during the RESOURCE_PHASE of the portlet lifecycle. However, it is not possible to test during the RESOURCE_PHASE since the jsf.js client-side library is in control of the XHR dispatched via f:ajax. -
setResponseStatus(int)
:The FacesBridge must follow the requirements in the JSF 2.0 JavaDoc. However, in a portlet environment it is only possible to set the response status during the
RESOURCE_PHASE
of the portlet lifecycle. Because of this, the FacesBridge will only be required to set the status code during theRESOURCE_PHASE
. Rather than callingHttpServletResponse.setStatus(int statusCode)
, the FacesBridge must call the new Portlet 3.0ResourceResponse.setStatus(int statusCode)
method. In all other phases of the portlet lifecycle, callingExternalContext.setResponseStatus(int statusCode)
is a no-op for the FacesBridge. [6.151]. -
responseFlushBuffer()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpServletResponse.flushBuffer()
the FacesBridge must callMimeResponse.flushBuffer()
. It is only valid to call this method during the HEADER_PHASE, RENDER_PHASE, and RESOURCE_PHASE of the portlet lifecycle. [6.152] -
setResponseContentLength(int)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
ServletResponse.setContentLength(int)
the FacesBridge must callResourceResponse.setContentLength(int)
. It is only valid to call this method during the RESOURCE_PHASE of the portlet lifecycle. [6.153]. -
encodeBookmarkableURL(String,Map<String,List<String>>)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, the requirements are satisfied by returning the
toString()
return value ofBridgeURLFactory.getBridgeBookmarkableURL(FacesContext facesContext, String uri, Map<String, List<String>> parameters)
. [6.154]. -
encodeRedirectURL(String,Map<String,List<String>>)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, the requirements are satisfied by returning the
toString()
return value ofBridgeURLFactory.getBridgeRedirectURL(FacesContext facesContext, String uri, Map<String, List<String>> parameters)
. [6.155]. -
encodePartialActionURL(String)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, the requirements are satisfied by returning the
toString()
return value ofBridgeURLFactory.getBridgePartialActionURL(FacesContext facesContext, String uri)
. [6.156].
The following methods require an implementation that aren't adequately described in the Faces 2.1 ExternalContext
javadoc:
-
getSessionMaxInactiveInterval()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpSession.getMaxInactiveInterval()
the FacesBridge must callPortletSession.getMaxInactiveInterval()
. [6.157]. -
setSessionMaxInactiveInterval(int)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpSession.setMaxInactiveInterval(int)
the FacesBridge must callPortletSession.setMaxInactiveInterval(int)
. [6.158]. -
isSecure()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpServletRequest.isSecure()
the FacesBridge must callPortletRequest.isSecure()
. [6.159].
The following methods require an implementation that aren't adequately described in the Faces 2.2 ExternalContext
javadoc:
-
getApplicationContextPath()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, since the Portlet 3.0 API does not have an equivalent to
ServletContext.getContextPath()
, the FacesBridge must rely on the Faces runtime to discover the application context path during initialization. [6.160]. -
getSessionId(boolean)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, rather than call
HttpSession.getId()
the FacesBridge must callPortletSession.getId()
. [6.161].
-
getClientWindow()
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. [6.162].
-
setClientWindow(ClientWindow)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. [6.162].
The JSF 2.2 Javadoc defines the javax.faces.application.ResourceHandler
abstract class which is an extension point for
creating and retrieving resources such as images, scripts, CSS style sheets, Facelet documents, etc. The FacesBridge
will need to provide its own ResourceHandler
in the <resource-handler>
delegation chain in order to ensure that
resource URLs will work in a portlet environment. In a webapp/servlet environment, Faces resource URLs follow a
"/javax.faces.resource/resource_name?ln=library_name" type of syntax. The FacesBridge will need to transform such URLs
such that a resource name is specified as the "javax.faces.resource" parameter, rather than using
"/javax.faces.resource" as a resource path identifier.
The following methods require an implementation that aren't adequately described in the Faces 2.2 ExternalContext
javadoc:
-
handleResourceRequest(FacesContext)
:The FacesBridge must follow the requirements in the JSF 2.2 JavaDoc. However, the FacesBridge must call the following portlet-equivalent methods instead:
Servlet API Method Equivalent Portlet API Method HttpServletResponse.setStatus(int)
ResourceResponse.setStatus(int)
HttpServletResponse.setContentType(String)
ResourceResponse.setContentType(String)
HttpServletResponse.setContentLength(int)
ResourceResponse.setContentLength(int)
HttpServletResponse.setHeader(String,String)
ResourceResponse.setProperty(String,String)
-
isResourceURL(String)
:Returns
true
if the specified value is a resource URL according to the presence of a "javax.faces.resource" parameter, which is encoded according to the format ofResourceURL.toString()
by the underlying portlet container.
The Faces ViewHandler
is the pluggability mechanism that allows implementations to extend the JavaServer Faces
specification to provide their own handling of the activities in the Render Response and Restore View phases of the
request processing lifecycle. This allows for implementations to support different response generation technologies, as
well as different state saving/restoring approaches.
The bridge is required to provide an implementation of the ViewHandler
[nt]. This
implementation must be configured in the faces-config.xml
file packaged into the bridge's jar
file[nt]. The implementation must implement the decorator design pattern described in
section 10.4.5 in the JSF 1.2 specification[nt].
Because configuration is limited to using the faces-config.xml
file packaged into the bridge's jar
file,
ViewHandler
order can't be defined if other Faces extensions relying on the same ViewHandler
configuration technique
exist in the environment. The bridge implementation must safely cohabit with these other ViewHandler
s regardless of
precedence order in the particular runtime environment they execute in[nt]. To satisfy
this the bridge must delegate to its parent ViewHandler
for all methods unless otherwise indicated to do so by a
configuration parameter. For most methods this will be a strict delegation with no pre/post processing of the call. If
pre/post processing is necessary it must be done in a manner that doesn't interfere with the normally processing of the
other ViewHandler
s in the chain. To facilitate this, implementations are encouraged to subclass
javax.faces.application.ViewHandlerWrapper
.
Furthermore, where ever the bridge provides bridge specific ViewHandler
behavior, it must ensure this behavior is only
executed when executing a request via the bridge[nt]. Because the ViewHandler
is a
general Faces extension the bridge's ViewHandler
methods will be called if the bridge is in this application's
classpath regardless of whether the current request has been dispatched through the bridge.
The following ViewHandler
methods must meet specific bridge requirements (i.e.
have expected pre/post delegation processing):
createView()
: is responsible for returning theUIViewRoot
for the newly created view tree. The bridge, during a portlet request, should return aUIViewRoot
from itscreateView()
that supports (is annotated by)javax.portlet.faces.annotation.PortletNamingContainer
. Such aNamingContainer
ensures all ids in the tree are unique on a per portlet (instance) basis 6.6. This type ofUIViewRoot
must be returned unless the bridge delegatesUIViewRoot
creation and the result of that delegation is aUIViewRoot
whose implementation class (notinstanceof
) is notjavax.faces.component.UIViewRoot
[6.86].
The following ViewHandler
methods have no specific bridge requirements and hence its expected they will always be
delegated. If a bridge implementation does more then merely delegate if must satisfy the above cohabitation
requirements. This is particularly true for writeState
as overriding this commonly interferes with the application
developers desired state management. If getActionURL
is modified the bridge must ensure the resulting String
it
returns is a valid URL
. In particular it can't be an URL
derived from a portletResponse.createActionURL()
.
calculateCharacterEncoding()
calculateLocale()
calculateRenderKitId()
getActionURL()
getResourceURL()
initView()
restoreView()
writeState()
To properly maintain references to (updated) view state the bridge will likely have to provide its own StateManager
in
order to override the state writing process allowing it to inspect and preserve (update) the value of the
VIEW_STATE_PARAM
parameter it manages in its extended bridge scope
[5.1.2.2]. For example the bridge can override
StateManager.writeState(FacesContext context, Object state)
:
- replace the
ResponseWriter
with one it manufactures that writes to aStringWriter
- delegate the call so the state is output.
- copy the output back into the original
ResponseWriter
- parse the output in the
StringWriter
locating theVIEW_STATE_PARAM
parameter and value - copy the value and place it on a request attribute for the bridge to process later
The bridge must prevent the Faces action phases (ApplyRequestValues
, ProcessValidations
, UpdateModel
, and
InvokeApplication
) from executing if processing an event or rendering in a restored bridge request
scope[6.90] [5.1.2]. I.e. during either a
portlet's EVENT_PHASE
or HEADER_PHASE
, when the Faces Lifecycle
is executed to restore the view, the bridge must
ensure the lifecycle falls directly through to render after the view is restored. This is most conveniently supported by
implementing a PhaseListener
and calling FacesContext.renderResponse()
when invoked in the RestoreView
phase.
Faces relies on the Unified Expression Language architecture to ensure consistent EL evaluation in a JSP page where JSP expressions and Faces expressions can coexist. During a JSP EL resolution Faces extends the JSP resolvers to process/expose Faces unique variables. During a Faces EL resolution Faces provides the base resolvers that not only expose the Faces unique variables but also those that the JSP resolvers otherwise have access to during the scope of the page. In a servlet environment, this ensures evaluation consistency for the same expression whether within a JSP expression or a Faces expression. However because the EL types are resolved by different resolvers in different contexts when running in a portlet environment evaluation isn't always consistent. Its important to be aware of the following subtle differences in implicit object evaluation.
When running in a JSP context, JSP provides an ELResolver that recognizes and resolves the following implicit objects[6.100]:
applicationScope
-> aMap
that maps application-scoped attribute names to their valuescookie
-> aMap
that maps cookie names to a singleCookie
object. Cookies are retrieved according to the semantics ofHttpServletRequest.getCookies()
.header
-> aMap
that maps header names to a singleString
header value (obtained by callingHttpServletRequest.getHeader(String name)
)headerValues
-> aMap
that maps header names to aString[]
of all values for that header (obtained by callingHttpServletRequest.getHeaders(String)
)initParam
-> aMap
that maps context initialization parameter names to theirString
parameter value (obtained by callingServletContext.getInitParameter(String name)
)pageContext
-> thePageContext
pageScope
-> aMap
that maps page-scoped attribute names to their valuesparam
-> aMap
that maps parameter names to a singleString
parameter value (obtained by callingServletRequest.getParameter(String name)
)paramValues
->Map
that maps parameter names to aString[]
of all values for that parameter (obtained by callingServletRequest.getParameterValues(String name)
)requestScope
-> aMap
that maps request-scoped attribute names to their valuessessionScope
-> aMap
that maps session-scoped attribute names to their values
When the <portlet:defineObjects>
tag is used within this JSP page, the following variables are exposed and will be
implicitly resolved by this JSP EL resolver[6.100]:
portletConfig
: object of typejavax.portlet.PortletConfig
actionRequest
: object of typejavax.portlet.ActionRequest
(only accessible in anActionRequest
)actionResponse
: object of typejavax.portlet.ActionResponse
(only accessible in anActionRequest
)eventRequest
: object of typejavax.portlet.EventRequest
(only accessible in anEventRequest
)eventResponse
: object of typejavax.portlet.EventResponse
(only accessible in anEventRequest
)headerRequest
: object of typejavax.portlet.HeaderRequest
(only accessible in aHeaderRequest
)headerResponse
: object of typejavax.portlet.HeaderResponse
(only accessible in aHeaderRequest
)renderRequest
: object of typejavax.portlet.HeaderRequest
(only accessible in aHeaderRequest
)renderResponse
: object of typejavax.portlet.HeaderResponse
(only accessible in aHeaderRequest
)resourceRequest
: object of typejavax.portlet.ResourceRequest
(only accessible in aResourceRequest
)resourceResponse
: object of typejavax.portlet.ResourceResponse
(only accessible in aResourceRequest
)portletSession
: currentPortletSession
object.portletSessionScope
: immutableMap
containingPortletSession
attribute/values atPORTLET_SCOPE
.portletPreferences
: currentPortletPreferences
object.portletPreferencesValues
: immutableMap
containing entries equivalent toPortletPreferences.getMap()
.
Faces extends this behavior by providing its own ELResolver to recognize and resolve the following implicit objects[6.100]:
facesContext
-> theFacesContext
for this requestview
->facesContext.getViewRoot()
When running in a Faces context (outside of JSP execution) Faces provides the base implicit object resolver that recognizes and resolves the following implicit objects[6.101]:
application
->externalContext.getContext()
applicationScope
->externalContext.getApplicationMap()
cookie
->externalContext.getRequestCookieMap()
facesContext
-> theFacesContext
for this requestheader
->externalContext.getRequestHeaderMap()
headerValues
->externalContext.getRequestHeaderValuesMap()
initParam
->externalContext.getInitParameterMap()
param
->externalContext.getRequestParameterMap()
paramValues
->externalContext.getRequestParameterValuesMap()
request
->externalContext.getRequest()
requestScope
->externalContext.getRequestScope()
session
->externalContext.getSession()
sessionScope
->externalContext.getSessionMap()
view
->facesContext.getViewRoot()
The primary difference between the ELResolvers
used within the JSP
context vs outside this context is that the base
JSP ELResolver
is used to resolve the bulk of the implicit objects and that this resolution is based on the JSP
s
servlet objects in the page while outside this context these objects are resolved via the ExternalContext
. In a
portlet environment, because the JSP ELResolver
evaluates based on the servlet objects generated when dispatched from
the portlet environment while the JSF ELResolver
evaluates based on the ExternalContext
, the following difference
needs to be considered:
sessionScope
: ThisMap
contains theAPPLICATION_SCOPE
session attributes if used in JSP EL butPORTLET_SCOPE
session attributes if used in Faces EL[6.100,6.101].
In addition one will note that the Faces implicit object ELResolver recognizes three objects that the JSP Resolver doesn't[6.101]:
application
session
request
In a JSP ELContext
one references these objects indirectly via the
PageContext[6.100]. I.e.
${pageContext.servletContext}
${pageContext.session}
${pageContext.request}
These differ from the objects returned by the Faces EL Resolver in that[6.101]:
${pageContext.servletContext}
: This is an object of typeServletContext
while application is an object of typePortletContext
.${pageContext.session}
: This is an object of type servletSession
whilesession
is an object of typePortletSession
. The key difference is thatPortletSession
by default referencesPORTLET_SCOPE
attributes while the servletSession
is a window onto the portlet'sAPPLICATION_SCOPE
.${pageContext.request}
: This is an object of typeServletRequest
(through wrapped by the portlet request) whilerequest
is an object of typePortletRequest
.
As noted above, when the <portlet:defineObjects>
tag is used, the following variables are exposed in the JSP page and
will be implicitly resolved by the JSP EL resolver[6.100]:
portletConfig
: object of typejavax.portlet.PortletConfig
actionRequest
: object of typejavax.portlet.ActionRequest
(only accessible in anActionRequest
)actionResponse
: object of typejavax.portlet.ActionResponse
(only accessible in anActionRequest
)eventRequest
: object of typejavax.portlet.EventRequest
(only accessible in anEventRequest
)eventResponse
: object of typejavax.portlet.EventResponse
(only accessible in anEventRequest
)headerRequest
: object of typejavax.portlet.HeaderRequest
(only accessible in anHeaderRequest
)headerResponse
: object of typejavax.portlet.HeaderResponse
(only accessible in anHeaderRequest
)renderRequest
: object of typejavax.portlet.RenderRequest
(only accessible in anRenderRequest
)renderResponse
: object of typejavax.portlet.RenderResponse
(only accessible in anRenderRequest
)resourceRequest
: object of typejavax.portlet.ResourceRequest
(only accessible in anResourceRequest
)resourceResponse
: object of typejavax.portlet.ResourceResponse
(only accessible in anResourceRequest
)portletSession
: currentPortletSession
object.portletSessionScope
: immutableMap
containingPortletSession
attribute/values atPORTLET_SCOPE
.portletPreferences
: currentPortletPreferences
object.portletPreferencesValues
: immutableMap
containing entries equivalent toPortletPreferences.getMap()
.
The bridge must provide a corresponding Faces EL resolver that recognizes these variable names and resolves them to the same object as the JSP resolver[6.101].
Because JSP EL evaluation and Faces EL evaluation are handled by different resolvers, the following differences are noted:
portletSessionScope
: This is an immutableMap
when referenced in a JSP expression but a mutableMap
when referenced in a Faces expression.
The bridge's ELResolver must additionally recognize and resolve identically the following EL object references regardless of whether its evaluating in a JSP or Faces expression[6.100,6.101]:
httpSessionScope
: mutableMap
containingPortletSession
attribute/values atAPPLICATION_SCOPE
.mutablePortletPreferencesValues
: mutableMap
of typeMap<String, javax.portlet.faces.preference.Preference>
. This EL variable provides read/write access to each portlet preference.
The bridge's ELResolver must be added through configuration within its faces-config.xml. e.g.
<el-resolver>
javax.portlet.faces.el.PortletELResolver
</el-resolver>
The ELResolver must be implemented as follows[6.100,6.101]:
ELResolver method | implementation requirements | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
getValue |
If running in a non-portlet request or base is non-null return null .
If evaluating a JSP expression (non-Faces expression) and property is portletConfig , headerRequest , or
headerResponse , renderRequest , or renderResponse , return null .
If base is null and property is null , throw PropertyNotFoundException .
If none of the above and base is null and property is a String equal to one of the above names, call
setPropertyResolved(true) on the argument ELContext and return result, where property and result are
as follows:
If base is null , and property does not match one of the above property names, return null. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
getType |
If running in a non-portlet request or base is non-null, return null.
If base is null and property is null , throw PropertyNotFoundException .
If base is null and property is a String equal to any of the above names, call
setPropertyResolved(true) on the argument ELContext and return null to indicate that no types are
accepted to setValue() for these attributes.
Otherwise, null; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
setValue |
If running in a non-portlet request or base is non-null, return null.
If base is null and property is null , throw PropertyNotFoundException .
If base is null and property is a String equal to any of the above names throw
javax.el.PropertyNotWriteableException , since these objects are read-only. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
isReadOnly |
If running in a non-portlet request or base is non-null, return true.
If base is null and property is null , throw PropertyNotFoundException .
If base is null and property is a String equal to any of the above names call
setPropertyResolved(true) on the argument ELContext and return true. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
getFeatureDescriptors | If base is non-null, return null.
If base is null , return an Iterator containing java.beans.FeatureDescriptor instances, one for each of
the above names. It is required that all of these FeatureDescriptor instances set Boolean.TRUE as the value of the
ELResolver.RESOLVABLE_AT_DESIGN_TIME attribute. For the name and short of FeatureDescriptor, return the EL object name.
The appropriate Class must be stored as the value of the ELResolver.TYPE attribute as follows:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
getCommonPropertyType | If base is non-null, return null.
If base is null and return String.class |
The mutablePortletPreferencesValues EL object allows one to read and update a portlet preference via EL. It relies on
the bridge defined javax.portlet.faces.preference.Preference
interface which allows one to expose each portlet
preference as an individual object making operations on portlet preferences EL accessible. Consult the
javax.portlet.faces.preference.Preference
javadoc for specific descriptions and requirements of objects implementing
this interface. In general there is a corresponding method for each operation in javax.portlet.Preferences
that can be
done on a specific preference. For example, a preference named "title" managed by the javax.portlet.Preferences
object
could have its value accessed using its corresponding javax.portlet.faces.preference.Preference
instance via
title.PrefObj.getValue()
rather than the typical preferences.getValue("title")
. Equivalent EL access would be:
"#{mutablePortletPreferencesValues['title'].value"
.
Though operations performed on javax.portlet.faces.preference.Preference
objects are immediately passed through to the
underlying portletPreferences
object, because the portletPreferences
object requires an explicit commit to preserve
these changes, developers must take care to finalize changes by calling portletPreferences.store()
directly before the
request ends. Typically this is done in the clients ActionHandler
executed during the InvokeApplication
phase.
Portlets are components that are aggregated by another application into a response page. As such a portlet is responsible for namespacing its markup to ensure its names don't collide with other parts of the aggregated page even when that aggregated page contains additional instances of this portlet. Traditionally, because the Java Portlet standard assumes the aggregated page isolates each portlet in a manner that allows discrete forms, namespacing is only required for global names such as javascript functions and variables. Unfortunately, many of today's Faces renderkits rely on this type of client side javascript necessitating namespacing when run in the portlet environment.
Additionally, with the emergence of consumer environments based on JSF and .NET in which such forms are collapsed into a a single all encompassing page form, the issue of namespacing form fields has emerged. Though from the standards perspective such consumers still have the burden of parsing and transforming the portlet markup to work in the single form environment, the ability for consumers to do this is restricted by both its needs to return a response to the user quickly and the complexity of locating (javascript) references to field names. Portlets, therefore, though not required, are encouraged to namespace not only their global (client) references but also their form fields as well.
Faces supports a notion of namespacing elements in its view tree which in turn impacts form field names and renderkit
resources such as its javascript names. A namespace is introduced using a concept called a NamingContainer
. When Faces
needs to construct a name it ascends the view tree looking for the closest parent that implements NamingContainer
. If
it finds one this parent gets an opportunity to return a namespace that will be incorporated into the name.
Though structurally supportive, Faces however doesn't inherently provide proper portlet namespacing. The bridge needs to
introduce this support. This is done by returning a UIViewRoot
from ViewHandler.createView()
that implements
NamingContainer
in a manner whereby the generated container name is constructed in part by using the unique namespace
Id
of the portlet. More specifically, a UIViewRoot
with the javax.portlet.faces.annotation.PortletNamingContainer
annotation must implement getContainerClientId()
to return a String
containing (at least in part) the portlet's
namespace Id
, if and only if, called during a portlet request[6.91]. The namespace Id
used in processing getContainerClientId()
must be consistent for the lifetime of the view (across save and
restore)[6.92]. Because getContainerClientId() can be called during various portlet
lifecycle phases (action, header, or resource)[6.93], care should be taken in
implementing this support to ensure such consistency as Portlet 1.0 containers only expose the portlet's namespace Id
during the render phase and hence ExternalContext.encodeNamespace()
throws an exception if called during a portlet
action request.
The convenience class javax.portlet.faces.PortletNamingContainerUIViewRoot
[6.94] is
provided to simplify adding portlet namespacing for Faces extensions (and for internal bridge usage). This class can
either be used directly or subclassed. The class is annotated with the
javax.portlet.faces.annotation.PortletNamingContainer
annotation[6.95] ensuring the
bridge will recognize this UIViewRoot
as one that implements the portlet namespacing behavior. It implements
getContainerClientId()
to meet the above requirements[6.96]. In addition,
getContainerClientId()
returns null
for non-portlet requests. This ensures the class can be used by the bridge as a
replacement for the standard javax.faces.component.UIViewRoot
because it ensures that non-portlet behavior runs
unchanged, without NamingContainer
function.
As indicated, annotating the UIViewRoot
class with javax.portlet.faces.annotation.PortletNamingContainer
allows the
bridge's FacesContext
to detect that the response will be portlet namespaced. To signal this behavior to the consumer,
FacesContext.setViewRoot()
sets the "X-JAVAX-PORTLET-FACES-NAMESPACED-RESPONSE
" response property with a value of
"true
"[nt]. Consumers needing to do response parsing to meet its namespacing
requirements (e.g. when inserting the response into a single overall page form) can use the existence of this property
as an indication that the form fields in the portlet response have already been properly namespaced and hence need not
be fixed up as part of the form parsing process.
When rendering, Faces depends on distinguishing between renders that follow action processing within the same request
and renders that do not. This is determined by calling ResponseStateManager.isPostback()
. Because portlet renders
occur in distinct requests from actions, the state Faces depends on to make this determination isn't naturally present.
As discussed in section 5.1.2 the bridge is required to ensure the existence
and/or absence of such state within its header phase in order to ensure proper execution of isPostback()
.
Specifically, the bridge is required to always preserve the ResponseStateManager.VIEW_STATE_PARAM
parameter in each
bridge request scope. This is done at the at the end of the ACTION_PHASE
and EVENT_PHASE
phase. Furthermore it must
restore this request parameter at the beginning of each HEADER_PHASE
phase that corresponds to this bridge request
scope such that a call to ExternalContext.getRequestParameterMap().get(ResponseStateManager.VIEW_STATE_PARAM)
returns
the restored value[6.97]. Finally, when its able to restore this parameter the bridge
must also set the request attribute javax.portlet.faces.isPostback
with a Boolean
object whose value is
Boolean.TRUE
[6.98]. This allows alternative isPostback()
implementations that do
not rely on the existence of the ResponseStateManager.VIEW_STATE_PARAM
to recognize they are running in a postback
situation.
Faces requires that all managed beans be given the opportunity to clean themselves up when they are being removed from
one of the three container scopes (application, session, request). The function is managed via annotations and
injection. A managed bean with one or more public no-argument void return methods annotated with
javax.annotation.PreDestroy
will be called when either the object is removed from scope or the scope terminates.
When running in the bridge, the lifetime of the application and session scopes aren't modified but the request scope is.
The bridge implements an extended request scope called the bridge request scope. This scope preserves managed beans
across physical requests ensuring that applications written in a style where request scoped managed beans are used to
maintain state between the Faces action and render lifecycles will function properly in the portlet's multi-request
lifecycle. However, because bridge request scope data is transferred into the portlet request scope when processing a
request, special handling is required by managed beans utilizing the annotation to avoid releasing the bean prematurely.
This is because the bridge can't prevent the PreDestroy
method from being called when the portlet request scope ends
even though it is managing the attribute in its request scope. I.e. managed beans managed by the bridge in its bridge
request scope will still be notified they are being destroyed at the end of each portlet request. To work properly
clients must change their managed bean implementations for those beans not excluded from the bridge request scope and
the bridge must provide new (additional) mechanisms.
Managed beans that want to utilize PreDestroy
and run properly when not explicitly excluded from the bridge request
scope must:
- Create separate but equal methods for handling the cleanup in the bridge environment. This distinct method(s) is
identified by the
BridgePreDestroy
annotation (javax.portlet.faces.annotation.BridgePreDestroy
). - Add a new public no-argument void return method annotated with
BridgeRequestScopeAttributeAdded
(javax.portlet.faces.annotation.BridgeRequestScopeAttributeAdded
). This method is called when the managed bean is added to the portlet request scope and it will be preserved by the bridge in the bridge request scope. When called a managed bean is expected to set internal state such that when itsPreDestroy
method(s) is called (later) it can check this state and if it indicates the request is running under the management of the bridge thePreDestroy
returns without doing any cleanup. This mechanism works around the issues related to the bridge being unable to disable the execution of thePreDestroy
method even when it continues to manage this bean in its request scope. - Modify each method annotated with
PreDestroy
to check if its executing under bridge management and if so return without performing any cleanup.
To satisfy the Faces requirement that managed beans managed in the bridge's request scope have an opportunity to release
themselves when the bridge request scope ends, the bridge must provide the following once it has acquired a
FacesContext
for a given request:
- When the bridge preserves a request attribute in the bridge request scope, the bridge must execute on the attribute's
value all public no argument void return methods annotated by
BridgeRequestScopeAttributeAdded
[nt/6.44]. - When an attribute that is currently maintained in the bridge's request scope is explicitly removed from the
container's request scope or its value replaced, the bridge must execute on the (old) attribute's value any public
no-argument void return method annotated by
BridgePreDestroy
if executing in the action phase[nt/6.44]. Note: because the bridge request scope isn't updated during its header phase replace/removal of an attribute's value from the container's request scope must not cause theBridgePreDestroy
method(s) to be called[nt/6.44]. - When an attribute that is currently maintained in the bridge's request scope is implicitly removed from the
container's request scope (such as when the container's request scope ends), the bridge does not notify the attribute's
BridgePreDestroy
methods[nt/6.44]. This is because the attribute is still managed in the bridge request scope though removed from the underlying container request scope which is terminating. - When the bridge is terminating a bridge request scope, the bridge must iterate over all managed attributes and execute
on the attribute's value any public no-argument void return method annotated by
BridgePreDestroy
[nt/6.44].
Faces resolves the renderkit used in a given request by first looking for a request parameter whose name is the value of
ResponseStateManager.RENDER_KIT_ID_PARAM
. If this parameter doesn't exist the id is next determined from a
configuration parameter in the application's faces-config.xml
and finally an internal setting. Given that the
faces-config.xml
is an application wide setting, the request parameter is the sole mechanism for managing the needs of
portlets that use distinct renderkits. As this may not be uncommon and most portlets use the same renderkit throughout
all its views, the bridge simplifies the use of this request parameter if the proper context attribute has been set
prior to it being initialized.
Specifically, when the bridge is initialized, if the portlet context attribute
javax.portlet.faces.<portletName>.defaultRenderKitId
is set, the bridge is responsible for ensuring that in every
request the request parameter Map
(s) returned from ExternalContext.getRequestParameterMap()
and
ExternalContext.getRequestParameterValuesMap()
and the Iterator
returned from the
ExternalContext.getRequestParameterNames()
contain an entry for
ResponseStateManager.RENDER_KIT_ID_PARAM
[6.135]. In the Map
(s), the value for
this entry must be the value from the underlying request, if it exists, otherwise it must be the value in the
javax.portlet.faces.<portletName>.defaultRenderKitId
context attribute[6.135].