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.
6.1 ExternalContext
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.
6.1.1 FacesContextFactory
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.
6.1.2 FacesContext
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:
- 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 the inputURL
unchanged[6.26].
- If the inputURL
's scheme specific part is portlet:[6.xxx] 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 the String (URL path)
returned after calling ViewHandler.getActionURL()
passing the current viewId[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, 6.34].
- 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 named javax.portlet.faces.BackLink.
If it does replace it with a parameter whose name is the
value of this parameter and whose value is the String (URL path)
returned after calling ViewHandler.getActionURL()
passing the current viewId
followed by ExternalContext.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].
- If
the inputURL
is hierarchical and targets a resource
that is within this application:
- if the inputURL is a
relative URL
(i.e. it is
neither absolute nor starts with a '/') then the inputURL 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 to dispatch() to
the current view.
- ensure that the inputURL
(potentially modified by the previous step) is a fully qualified path URI
(i.e.contains the context path)[6.31].
- if the resulting inputURL
contains a query string parameter named javax.portlet.faces.BackLink
then replace it with a parameter whose name is the value of this
parameter and whose value is the String (URL path)
returned after calling ViewHandler.getActionURL()
passing the current viewId[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 of h: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[6.xxx]
- the target is a Faces resource, one that in a
servlet environment would be processed running through the FacesServlet[6.xxx].
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.
- if returning an in protocol resource, return the String
representation of a resourceURL created using response.createResourceURL()
after processing PortletURL
related state modifications[6.xxx]:
- 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 of true
or false
is translated into the boolean
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 to encodeActionURL.
I.e. if
the incoming url is xml escaped the 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 the URL 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
the URL
regardless of any stipulation regarding base encoding.
- 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 type String)
are the first (or only) value for each header
name returned by the underlying request[6.38,6.39].
The returned Map
must implement the entire contract for an unmodifiable Map as
described
in the JavaDocs for java.util.Map
[6.38,6.39]. 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
methods getProperty()
and getPropertyNames()
except when executing a RENDER_REQUEST or an EVENT_REQUEST.
Within
a RENDER_REQUEST or EVENT_REQUEST,
the map must exclude the CONTENT-TYPE and CONTENT-LENGTH
properties (if they are present
in the underlying request)[6.38, 6.xxx].
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
or RESOURCE_PHASE:
Accept,
Accept-Language,
Content-Type,
and Content-Length[6.39, 6.xxx].
When executing during a RENDER_PHASE
or an EVENT_PHASE
the bridge must only ensure that Accept and Accept-Language
exist (and as noted above that Content-Type
and Content-Length
don't exist)[6.38, 6.xxx].
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 by
getResponseContentTypes()
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 by
getLocales() 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 by getContentType()
and getCharacterEncoding() 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 if getContentType() returns a non-null value.
The character set portion of this header must only be
represented if getCharacterEncoding() returns a non-null value.
Content-Length:
The value returned for this header must be the result of
properly encoding the values returned by getContentLength() 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 if getContentLength() 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 type String[]) are
all of the value for
each header name returned by the underlying request[6.40, 6.41].
The returned Map
must implement the entire contract for an unmodifiable Map as
described
in the JavaDocs for java.util.Map
[6.40, 6.41]. 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 the javax.portlet.PortletRequest
methods getProperty()
and getPropertyNames()
except when executing a RENDER_REQUEST or an EVENT_REQUEST.
Within
a RENDER_REQUEST or EVENT_REQUEST, the map must exclude the CONTENT-TYPE property (if it is present
in the underlying request)[6.40, 6.xxx].
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
or RESOURCE_PHASE:
Accept,
Accept-Language,
Content-Type,
and Content-Length[
6.41, 6.xxx].
When executing during a RENDER_PHASE
or an EVENT_PHASE
the bridge must only ensure that Accept and Accept-Language
exist (and as noted above that Content-Type
doesn't exist)[6.40, 6.xxx].
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 by
getResponseContentTypes()
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 by
getLocales() 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 by getContentType()
and getCharacterEncoding() 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 if getContentType() returns a non-null value.
The character set portion of this header must only be
represented if getCharacterEncoding() returns a non-null value.
Content-Length:
The value returned for this header must be the result of
properly encoding the values returned by getContentLength() 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 if getContentLength() returns a value other then -1.
- getRequestMap():
Return a mutable Map
representing the request scope attributes for the current application[6.42].
The returned Map
must implement the entire
contract for a modifiable map as described in the JavaDocs for java.util.Map
.
Modifications made in the Map
must cause the
corresponding changes in the set of request scope attributes.
Particularly the clear()
, remove()
,
put()
, putAll()
,
and get()
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.44/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 the javax.portlet.PortletRequest
methods getAttribute()
, getAttributeNames()
,
removeAttribute()
, and setAttribute()
.
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 type String) are the first (or only) value for each
parameter name returned by the underlying request[6.45]. The
returned Map
must implement the entire contract for an unmodifiable map as described
in the JavaDocs for java.util.Map
This Map must be
composed from the
set of parameters available via the javax.portlet.PortletRequest
methods getParameter()
and getParameterNames()
plus any additional parameter names encoded in the (query string) of
the viewId[6.47].
This
later situation primarily occurs when using a default viewId provided
by the portlet.
In addition, during a portlet's RENDER_PHASE, if not
otherwise already in the Map,
the bridge must include those parameters managed in the corresponding
bridge request scope. This always includes the ResponseStateManger.VIEW_STATE_PARAM
parameter[6.45].
The preservation/inclusion of the rest of the
action parameters depends on the javax.portlet.faces.[portlet
name].preserveActionParams
portlet
context attribute. If this context attribute exists and has a
value of Boolean.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 an Iterator
over the values
returned by the javax.portlet.PortletRequest
method getParameterNames()
[6.48]
plus any additional parameter names encoded in the (query string) of
the
viewId[6.50].
This later situation primarily occurs when using a
default viewId
provided by the portlet.
In addition, during a portlet's RENDER_PHASE, if not
otherwise already in the Iterator,
the bridge must include those parameter names managed in the
corresponding bridge request scope. This always includes the ResponseStateManger.VIEW_STATE_PARAM
parameter[6.48].
The preservation/inclusion of the rest of the action
parameters depends on the javax.portlet.faces.[portlet
name].preserveActionParams
portlet
context attribute. If this context attribute exists and has a
value of Boolean.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 type String[]) are all of the values for
each parameter name returned by the underlying request[6.51].
The returned Map
must implement the entire contract for an unmodifiable map as described
in the JavaDocs for java.util.Map
.
This must be the
set of parameter values available via the javax.portlet.PortletRequest
methods getParameterValues()
and getParameterNames()
plus any additional parameter names encoded in the (query string) of
the
viewId[6.53]. This
later situation primarily occurs when using a default viewId provided
by the portlet.
In addition, during a portlet's RENDER_PHASE, if not
otherwise already in the Map,
the bridge must include those parameter names managed in the
corresponding bridge request scope. This always includes the ResponseStateManger.VIEW_STATE_PARAM
parameter[6.51].
The preservation/inclusion of the rest of the action
parameters depends on the javax.portlet.faces.[portlet
name].preserveActionParams
portlet
context attribute[6.52].
If this context attribute exists and has a
value of Boolean.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, return null
.
This value must represent the path portion of the current
target viewId.
Because the portlet model doesn't support a (servlet) equivalent notion
of pathInfo
and servletPath,
the bridge must manufacture these values based on the target viewId.
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 default viewId
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 .4.4 in the Servlet 2.5
specification[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
and servletPath,
the bridge must manufacture these values based on the target viewId.
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 default viewId
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 .4.4 in the Servlet 2.5
specification[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 or RESOURCE_PHASE,
returns the value from the corresponding action request.getCharacterEncoding()[6.57, 6.xxx].
If called
during the RENDER_PHASE or
EVENT_PHASE
it returns null[6.56, 6.xxx].
- getRequestContentType():
Return the MIME Content-Type for this request. If called
during the ACTION_PHASE
or RESOURCE_PHASE,
returns the value from the corresponding action request.getContentType()[6.59, 6.xxx].
If called
during he
RENDER_PHASE or
EVENT_PHASE
it returns null[6.58, 6.xxx].
- getResponseCharacterEncoding():
Returns the name of the character encoding (MIME charset) used for the
body sent in this response. If called during the RENDER_PHASE or RESOURCE_PHASE,
returns the value from the
corresponding render response.getCharacterEncoding()[6.60, 6.xxx].
If called during the ACTION_PHASE or EVENT_PHASE
it throws an IllegalStateException[6.61, 6.xxx].
- getResponseContentType():
Return the MIME Content-Type for this response. If called during the RENDER_PHASE or RESOURCE_PHASE,
returns the value from the
corresponding render response.getContentType()[6.62, 6.xxx].
If called during the ACTION_PHASE or EVENT_PHASE
it throws an IllegalStateException[6.63, 6.xxx].
- 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, the response
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",
call ActionResponse.sendRedirect()
passing the url.
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.
During an Event Request[6.xxx]:
- 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 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.
During a Render 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 nonFaces view
then throw an IllegalStateException[6.66].
- otherwise, encode the redirect target and call
FacesContext.responseComplete()to
ensure the bridge will cease rendering its current view prior to
returning any response content. Instead, render the redirect
target and returns its output as the response[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.
During a Resource Request[6.xxx]:
- The redirect is
ignored. Take no action.
6.1.3.2
Methods that conform with Faces 1.2 Javadoc
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
method getNamespace()
[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 the javax.portlet.PortletContext
methods getAttribute()
, getAttributeNames()
,
removeAttribute()
, and setAttribute()
.
The returned Map
must implement the
entire contract for a modifiable map as described in the JavaDocs for java.util.Map
.
Modifications made in the Map
must cause the
corresponding changes in the set of application scope attributes.
Particularly the clear()
, remove()
,
put()
, putAll()
,
and get()
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 with javax.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 the PreDestroy
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
, or FORM_AUTH
.
This must be the value returned by the javax.portlet.http.PortletRequest
method getAuthType()
.
-
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). This must be the result of
the javax.portlet.PortletContext
method getInitParameter(name)
[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 returned Map
must
implement the entire contract for an unmodifiable map as described in
the JavaDocs for java.util.Map
.
This result must be as if it were synthesized by calling the javax.portlet.PortletContext
method getInitParameterNames
, and putting
each configured parameter name/value pair into the result.
-
getRemoteUser():
Return the login name of the user making the current
request if any; otherwise, return null
.
This must be the value returned by the javax.portlet.http.PortletRequest
method getRemoteUser()
[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
method getContextPath()
[6.74].
-
getRequestCookieMap():
Return an immutable Map
whose
keys are the set of cookie names included in the current request, and
whose values (of type javax.servlet.http.Cookie
)
are the first (or only) cookie for each cookie name returned by the
underlying request. The returned Map
must implement the entire contract for an unmodifiable map as described
in the JavaDocs for java.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 the javax.portlet.PortletRequest
method getLocale()
[6.76].
-
getRequestLocales():
Return an Iterator
over the
preferred Locale
s specified in the request,
in decreasing order of preference. This must be an Iterator
over the values returned by the javax.portlet.PortletRequest
method getLocales()
[6.77].
-
getResource():
Return a URL
for the application
resource mapped to the specified path, if it exists; otherwise, return null
.
This must be the value returned by the javax.portlet.PortletContext
method getResource(path)
[6.78].
-
getResourceAsStream():
Return an InputStream
for an
application resource mapped to the specified path, if it exists;
otherwise, return null
. This must
be the value returned by the javax.portlet.PortletContext
method getResourceAsStream(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 the javax.portlet.PortletContext
method getResourcePaths(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 is true
,
create (if necessary) and return a session instance associated with the
current request. If the create
parameter is false
return any existing session instance associated with the current
request, or return null
if there is no such
session. This method must return the result of calling getPortletSession(create)
on the underlying javax.portlet.PortletRequest
instance[6.82].
- getSessionMap():
Return a mutable Map
representing the session
(PORTLET_SCOPE) scope attributes for the
current portlet[6.83]. The returned Map
must implement the entire contract for a modifiable map as described in
the JavaDocs for java.util.Map
. Modifications
made in the Map
must cause the corresponding
changes in the set of session scope attributes. Particularly the clear()
, remove()
, put()
,
and get()
operations must take the
appropriate action on the underlying data structure. Accessing
attributes via this Map
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 with javax.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 the PreDestroy
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 the PORTLET_SCOPE available via the javax.portlet.PortletSession
methods getAttribute()
, getAttributeNames()
, removeAttribute()
, and setAttribute()
.
-
getUserPrincipal():
Return the Principal
object
containing the name of the current authenticated user, if any;
otherwise, return null
. This must
be the value returned by the javax.portlet.http.PortletRequest
method getUserPrincipal()
[6.85].
-
isUserInRole():
Return true
if the currently
authenticated user is included in the specified role. Otherwise, return
false
. This must be the value
returned by the javax.portlet.http.PortletRequest
method isUserInRole(role)
.
-
log():
Log the specified message to the application object. This
must be performed by calling the equivalent form of the
javax.portlet.PortletContext
method log()
.
6.2 ViewHandler
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 ViewHandlers
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
ViewHandlers
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.
6.2.1 Method
Requirements
The following
ViewHandler
methods must meet specific bridge requirements (i.e. have expected
pre/post delegation processing):
- createView():
createView() is
responsible for returning the UIViewRoot
for the newly created view tree. The bridge, during a
portlet request, should return a UIViewRoot from
its createView()
that supports (is annotated by) javax.portlet.faces.annotation.PortletNamingContainer. Such a NamingContainer ensures all ids in the tree are
unique on a per portlet (instance) basis [6.6].
This
type of UIViewRoot
must be returned unless the bridge delegates UIViewRoot
creation and the result of that delegation is a UIViewRoot
whose implementation class (not instanceof) is not
javax.faces.component.UIViewRoot[6.86].
- renderView():
The bridge must
implement renderView
as follows:
If the request isn't a portlet request, delegate renderView to
the
parent and return the result without taking any further action.
Otherwise[6.87]:
- DEFAULT behavior:
return the result by delegating the call to its parent within
a try/catch block that catches Throwable.
If and only if a Throwable
is caught, render the view directly accordingly to the rules described
below.
- ALWAYS_DELEGATE behavior:
return the result by delegating the call to its parent
regardless of whether the delegation results in raising a Throwable.
I.e. never render the view accordingly to the rules described
below.
- NEVER_DELEGATE
behavior:
never delegate the call to its parent. Rather always
render the view directly according to the rules described below.
where DEFAULT, ALWAYS_DELEGATE, and NEVER_DELEGATE are the corresponding values of
the per portlet bridge initialization attribute renderPolicy as described in [3.2].
If no such setting exists renderView implements DEFAULT
behavior.
When directly rendering the view, the bridge must render in a manner
that provides the
semantics defined by section 7.5.2 in the JSF 1.2 specification.
Specifically it must attempt to ensure that it is possible for the
markup
generated by the view to be interleaved with native markup in a manner
that preserves order as indicated in that section. Unfortunately,
such interleaving can only be accomplished using Faces
implementation dependent code and hence isn't provided natively by the
bridge. Rather, the bridge defines mechanism(s) that allow a
portlet to configure an appropriate render handler to support this
behavior. There are two mechanisms [see
Chapter 7]:
- the
portlet 1.0 bridge mechanism that relied on configuring a servlet
filter that wraps the response with a wrapper that supports the Faces
implementation specific APIs for handling the JSP write before/after
response behavior.
- provide a Portlet 2.0 PortletResponseWrapper which
supports the same APIs.
To support these mechanisms, the bridge's render(), prior
to calling dispatch()
must:
- Add an
attribute named javax.portlet.faces.RenderContentAfterView
with a java.lang.Boolean
value of Boolean.TRUE to
the request
object[6.88].
- Cache the
current
response (known to the Faces ExternalContext)
so it can be reset later.
- Create an
instance of a PortletResponseWrapper object that implements javax.portlet.faces.BridgeWriteBehindResponse and set it in the Faces ExternalContext
by calling ExternalContext.setResponse()[6.xxx]
. If an instance class is configured
[see 7.2],
it must be used[6.xxx], otherwise either javax.portlet.faces.application.BridgeViewHandlerRenderResponseWrapper
or javax.portlet.faces.application.BridgeViewHandlerResourceResponseWrapper
(depends on the portlet phase) or their equivalent is used.
Immediately
following the
dispatch():
- Reset the
Faces ExternalContext
response by calling ExternalContext.setResponse() with the (current)
response cached in the step above[6.xxx].
- If the BridgeWriteBehindResponse
object's
hasFacesWriteBehindMarkup()
method returns true
and something (servlet
filter) hasn't already set the javax.portlet.faces.AfterViewContent attribute, support the write behind behavior by holding onto the BridgeWriteBehindResponse object or the content it
is buffering until after the view has been rendered. Otherwise write
the content directly to the response.
After the dispatch and after rendering the view (when one hasn't
already written the content directly to the response):
- retrieve buffered
content that should be
positioned after the rendered view from the request attribute javax.portlet.faces.AfterViewContent
(via
a call to ExternalContext.getRequestMap()).
If non-null, the type of this value is either byte[] or a char[].
- If non-null, copy the content into the response and
remove the attribute from the request Map[6.89].
- (otherwise) if
a BridgeWriteBehindResponse
has been used and your bridge implementation doesn't rely on this
request attribute to cache the content until after the view is
rendered, output its buffered content.
6.2.2 Other Methods
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()
6.3
StateManager
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 a StringWriter
- delegate the call so the state is output.
- copy the output back into the original ResponseWriter
- parse the output in the StringWriter
locating the VIEW_STATE_PARAM
parameter and value
- copy the value and place it on a request attribute for the
bridge to process later
6.4 Phase Listeners
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, 6.xxx] [5.1.2].
I.e. during either a portlet's EVENT_PHASE or RENDER_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.
6.5
Expression Language Resolution
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.
6.5.1 Implicit Objects
When running in a JSP context, JSP provides an ELResolver that
recognizes and resolves the following implicit objects
[6.100]:
applicationScope
-> a Map that maps application-scoped attribute names to their
values
cookie -> a
Map that maps
cookie names to a single Cookie object. Cookies are retrieved according
to the semantics of HttpServletRequest.getCookies().
header -> a
Map that maps
header names to a single String header value (obtained by calling
HttpServletRequest.getHeader(String name))
headerValues
-> a Map that maps header names to a String[] of all values for
that
header (obtained by calling HttpServletRequest.getHeaders(String))
initParam ->
a Map that maps
context initialization parameter names to their String parameter value
(obtained by calling ServletContext.getInitParameter(String name))
pageContext -> the PageContext
pageScope -> a Map that maps page-scoped attribute names to
their values
param
-> a Map that maps
parameter names to a single String parameter value (obtained by calling
ServletRequest.getParameter(String name))
paramValues
-> Map that maps parameter names to a String[] of all values for
that parameter (obtained by calling
ServletRequest.getParameterValues(String name))
requestScope
-> a Map that maps request-scoped attribute names to their values
sessionScope
-> a Map 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
type javax.portlet.PortletConfig
actionRequest: object of type javax.portlet.ActionRequest
(only accessible in an ActionRequest)
actionResponse:
object
of type javax.portlet.ActionResponse (only accessible in an
ActionRequest)
eventRequest: object of type javax.portlet.EventRequest (only accessible in an
EventRequest)
eventResponse:
object
of type javax.portlet.EventResponse (only accessible in an
EventRequest)
renderRequest: object of type javax.portlet.RenderRequest (only accessible in an
RenderRequest)
renderResponse:
object
of type javax.portlet.RenderResponse (only accessible in an
RenderRequest)
resourceRequest: object of type javax.portlet.ResourceRequest (only accessible in an
ResourceRequest)
resourceResponse:
object
of type javax.portlet.ResourceResponse (only accessible in an
ResourceRequest)
portletSession:
current PortletSession
object.
portletSessionScope:
immutable Map
containing PortletSession
attribute/values at PORTLET_SCOPE.
portletPreferences: current
PortletPreferences object.
portletPreferencesValues:
immutable Map
containing entries equivalent to PortletPreferences.getMap().
Faces extends this behavior by providing its own ELResolver to
recognize and resolve the following implicit objects
[6.100]:
facesContext
-> the FacesContext for this request
view ->
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
-> the FacesContext for this request
header ->
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
JSPs
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:
This
Map
contains the
APPLICATION_SCOPE
session attributes if used in JSP EL but
PORTLET_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 type ServletContext
while application
is an object of type PortletContext.
${pageContext.session}:
This is an object of type servlet Session while session is an
object of type PortletSession.
The key difference is that PortletSession
by default references PORTLET_SCOPE
attributes while the servlet Session
is a window onto the portlet's APPLICATION_SCOPE.
${pageContext.request}: This
is an object of type ServletRequest
(through wrapped by
the
portlet request) while request
is an object of type PortletRequest.
6.5.2 Bridge ELResolver
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
type javax.portlet.PortletConfig
actionRequest: object of type javax.portlet.ActionRequest
(only accessible in an ActionRequest)
actionResponse:
object
of type javax.portlet.ActionResponse (only accessible in an
ActionRequest)
eventRequest: object of type javax.portlet.EventRequest (only accessible in an
EventRequest)
eventResponse:
object
of type javax.portlet.EventResponse (only accessible in an
EventRequest)
renderRequest: object of type javax.portlet.RenderRequest (only accessible in an
RenderRequest)
renderResponse:
object
of type javax.portlet.RenderResponse (only accessible in an
RenderRequest)
resourceRequest: object of type javax.portlet.ResourceRequest (only accessible in an
ResourceRequest)
resourceResponse:
object
of type javax.portlet.ResourceResponse (only accessible in an
ResourceRequest)
portletSession:
current PortletSession
object.
portletSessionScope:
immutable Map
containing PortletSession
attribute/values at PORTLET_SCOPE.
portletPreferences: current
PortletPreferences object.
portletPreferencesValues:
immutable Map
containing entries equivalent to PortletPreferences.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].
In addition, the bridge must not resolve these
variables
outside of a Faces expression
[6.100].
Note: The mechanism
Faces provides for
registering a EL resolver causes the EL resolver to be inserted into
the resolution chain for both Faces expressions and JSP expressions.
For the above objects, the bridge's EL resolver must delegate
resolution to the JSP resolver within JSP expressions while resolving
them within Faces expressions.
Because JSP EL evaluation and Faces EL evaluation are handled by
different resolvers, the following differences are noted:
portletSessionScope:
This is an immutable Map
when referenced in a JSP expression but a mutable Map when
referenced in a Faces expression.
6.5.2.1 Additional Implicit Object Support for
Portlets
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:
mutable Map
containing PortletSession
attribute/values at APPLICATION_SCOPE.
mutablePortletPreferencesValues:
mutable Map
of type Map<String,
javax.portlet.faces.preference.Preference>. This
EL variable provides read/write access to each
portlet preference.
6.5.2.2 ELResolver Requirements
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 (nonFaces expression) and property is
either portletConfig,
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:
EL object name |
result |
portletConfig |
portletConfig
object (recommended implementation is to place the portletConfig object
on the
ELContext so can pull it here). |
actionRequest |
If within an ActionRequest
then ExternalContext.getRequest()
otherwise throw an ELException. |
actionResponse |
If within an ActionRequest
then ExternalContext.getResponse()
otherwise throw an ELException. |
eventRequest |
If within an EventRequest
then ExternalContext.getRequest()
otherwise throw an ELException. |
eventResponse |
If within an EventRequest
then ExternalContext.getResponse()
otherwise throw an ELException. |
renderRequest |
If within an RenderRequest
then ExternalContext.getRequest()
otherwise throw an ELException |
renderResponse |
If within an RenderRequest
then ExternalContext.getResponse()
otherwise throw an ELException. |
resourceRequest |
If within an ResourceRequest
then ExternalContext.getRequest()
otherwise throw an ELException. |
resourceResponse |
If within an ResourceRequest
then ExternalContext.getResponse()
otherwise throw an ELException. |
portletSession |
ExternalContext.getSession() |
portletSessionScope |
ExternalContext.getSessionMap() |
httpSessionScope |
an
internally constructed Map containing those portlet session attributes
at APPLICATION_SCOPE. |
portletPreferences |
ExternalContext.getRequest()).getPreferences() |
portletPreferencesValues |
ExternalContext.getRequest()).getPreferences().getMap() |
mutablePortletPreferencesValues |
An
internally constructed Map <String,
javax.portlet.faces.preference.Preference>. There is one entry
per portlet preference. The key is the preference
name. The value is an object representing a single portlet
preference
(as defined by this interface). Entries may not be added or deleted
but and entry can be changed. |
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 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 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:
EL
object name |
ELResolver.TYPE
value |
portletConfig |
javax.portlet.PortletConfig.class |
actionRequest |
javax.portlet.ActionRequest.class |
actionResponse |
javax.portlet.ActionResponse.class |
eventRequest |
javax.portlet.EventRequest.class |
eventResponse |
javax.portlet.EventResponse.class |
renderRequest |
javax.portlet.RenderRequest.class |
renderResponse |
javax.portlet.RenderResponse.class |
resourceRequest |
javax.portlet.ResourceRequest.class |
resourceResponse |
javax.portlet.ResourceResponse.class |
portletSession |
javax.portlet.PortletSession.class |
portletSessionScope |
Map.class |
httpSessionScope |
Map.class |
portletPreferences |
javax.portlet.PortletPreferences.class
|
portletPreferencesValues |
Map.class |
mutablePortletPreferencesValues |
Map.class |
The
shortDescription must be a suitable description depending on the
implementation. The expert and hidden properties must be false. The
preferred property must be true. |
getCommonPropertyType
|
If base is
non-null, return null.
If base is null and return String.class |
6.5.2.3 The
javax.portlet.faces.preference.Preference interface
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.
6.6 Namespacing
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 any portlet lifecycle phase (action or render)[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 its returns
getContainerClientId()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.
6.7 Supporting
isPostback() during RENDER_PHASE
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 render 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 RENDER_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.
6.8
Supporting PreDestroy Annotated Methods
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.
6.8.1 Managed
Bean Changes
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 its PreDestroy
method(s) is called (later) it can check this state and if it indicates
the
request is running under the management of the bridge the PreDestroy
returns without doing any cleanup. This mechanism works
around
the issues related to the bridge being unable to disable the execution
of the PreDestroy
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.
6.8.2 Bridge
requirements
To satisfy the
Faces requirement that managed beans managed in the bridge's request
scope have an opportunity to release themeselves when the bridge
request scope ends, the bridge must provide the following once it has
acquired a FacesContext for a given request: