See: Description
Class | Description |
---|---|
FacesViews |
FacesViews is a mechanism to use SEO-friendly extensionless URLs in a JSF application without the need to enlist
individual Facelet source files in some configuration file.
|
FacesViewsForwardingFilter |
This filter makes sure extensionless requests arrive at the FacesServlet using an extension on which that Servlet is
mapped, and that non-extensionless requests are handled according to a set preference.
|
FacesViewsResolver |
Facelets resource resolver that resolves mapped resources (views) to the folders from which
those views were scanned (like the the special auto-scanned faces-views folder).
|
FacesViewsViewHandler |
View handler that renders an action URL extensionless if a resource is a mapped one, and faces views has been set to
always render extensionless or if the current request is extensionless, otherwise as-is.
|
FacesViewsViewHandlerInstaller |
Installs the
FacesViewsViewHandler . |
UriExtensionRequestWrapper |
This wraps a request to an extensionless JSF view and provides an extension for
all methods that reveal the servlet path.
|
Enum | Description |
---|---|
ExtensionAction |
The action that is done when a Faces Views request with an extension is done.
|
FacesServletDispatchMethod | Deprecated
Since 2.6 As this is superfluous since Servlet 3.0.
|
PathAction |
The action that is done when a request for a public path from which faces views where scanned is done.
|
ViewHandlerMode | Deprecated
Since 2.6 As this is superfluous since Servlet 3.0.
|
This package contains the classes for the OmniFaces FacesViews feature.
FacesViews is a feature where a special dedicated directory (/WEB-INF/faces-views
), or optionally one or
more user specified directories, can be used to store Facelets source files.
All files found in these directories are automatically mapped as Facelets files and made available using both their original extension as well as without an extension (extensionless). Optionally scanning can be restricted to include only certain extensions.
With FacesViews, there is thus no need to list all Facelets views that should be accessed without an extension in some configuration file. Additionally, it thus automatically maps Facelets files to their original file extension, which prevents exposing the source code of those Facelets that happens with the default JSF mapping.
Scanning is done automatically and thus no further configuration is needed. The feature is compatible with
applications that don't have web.xml
or faces-config.xml
configuration files. As such, it
can be used as an alternative to declaring the FacesServlet
in web.xml
for
the .xhtml
to .xhtml
mapping.
Consider the following file structure and assume no further configuration has been done:
/WEB-INF/faces-views/index.xhtml /WEB-INF/faces-views/users/add.xhtml /normal.xhtml
This will make the Facelets available via the following URLs
(given a root deployment on domain example.com
):
example.com/index example.com/users/add example.com/index.xhtml (will redirect to /index by default) example.com/users/add.xhtml (will redirect to /users/add by default) example.com/normal.xhtml
Note that although the directory outside /WEB-INF/faces-views
is not scanned, the
FacesServlet
is mapped on all extensions found in
/WEB-INF/faces-views
, so this will also affect files outside this directory. In the above example
normal.xhtml
is thus also available via the .xhtml
extension, since the whole FacesServlet
is mapped on this.
Also note that the extension variants of the scanned views will redirect to the extensionless variants. This behavior can be changed (see below), so that these views are either directly available (no redirect) or are not available at all.
Consider the following web.xml
:
<context-param> <param-name>org.omnifaces.FACES_VIEWS_SCAN_PATHS</param-name> <param-value>/*.xhtml</param-value> </context-param>
And this file structure:
/page1.xhtml /foo/page2.xhtml /WEB-INF/resources/template.xhtml /script.js
This will make the Facelets available via the following URLs
(given a root deployment on domain example.com
):
example.com/page1 example.com/foo/page2 example.com/page1.xhtml (will redirect to /page1 by default) example.com/foo/page2.xhtml (will redirect to /foo/page2 by default)
Note that in the above example, /WEB-INF
was NOT scanned and thus template.xhtml
is not
made publicly available. Likewise /script.js
was also not scanned since it doesn't have the configured
extension (.xhtml
). Finally, although a web.xml
was used, there does not need to be a
mapping for the FacesServlet
in it.
Consider the following web.xml
:
<context-param> <param-name>org.omnifaces.FACES_VIEWS_SCAN_PATHS</param-name> <param-value>/*.xhtml/*</param-value> </context-param>
And this file structure:
/page1.xhtml /foo/page2.xhtml
This will make the Facelets available via the following URLs
(given a root deployment on domain example.com
):
example.com/page1 example.com/foo/page2 example.com/page1/foo (will forward to /page1 with dynamic path parameter "foo") example.com/page1/foo/bar (will forward to /page1 with dynamic path parameters "foo" and "bar") example.com/foo/page2/bar (will forward to /foo/page2 with dynamic path parameter "bar") example.com/foo/page2/bar/baz (will forward to /foo/page2 with dynamic path parameters "bar" and "baz") example.com/page1.xhtml (will redirect to /page1 by default) example.com/foo/page2.xhtml (will redirect to /foo/page2 by default)
The path parameters are injectable via @
Param
in the managed bean
associated with the page. Below example shows how they are injected in the managed bean associated with /page1.xhtml.
@Inject @Param(pathIndex=0) private String foo; @Inject @Param(pathIndex=1) private String bar;
The support for this so-called MultiViews feature which gets triggered when the path pattern is suffixed with
/*
was added in OmniFaces 2.5 and is not available in older versions.
Consider the following web.xml
:
<context-param> <param-name>org.omnifaces.FACES_VIEWS_SCAN_PATHS</param-name> <param-value>/*.xhtml, /foo/*</param-value> </context-param>
And this file structure:
/page1.xhtml /foo/page2.xhtml
This will make the Facelets available via the following URLs
(given a root deployment on domain example.com
):
example.com/page1 example.com/foo/page2 example.com/foo/page2/bar (will forward to /foo/page2 with dynamic path parameter "bar") example.com/foo/page2/bar/baz (will forward to /foo/page2 with dynamic path parameters "bar" and "baz") example.com/page1.xhtml (will redirect to /page1 by default) example.com/foo/page2.xhtml (will redirect to /foo/page2 by default)
Note that on contrary to previous example example.com/page1/foo
and example.com/page1/foo/bar
are not available as the MultiViews feature is only enabled on /foo/*
.
If a <welcome-file>
is defined in web.xml
that's scanned by FacesViews
AND REDIRECT_TO_EXTENSIONLESS
is used (which is the default, see below), it's necessary
to define an extensionless welcome file to prevent a request to /
being redirected to
/[welcome file]
. E.g. without this http://example.com
will redirect to say
http://example.com/index
.
For example:
<welcome-file-list> <welcome-file>index</welcome-file> </welcome-file-list>
If you're using the MultiViews feature on a site-wide basis and have a welcome file configured for it, then basically
any request which doesn't match any physical file will end up in that welcome file. In case this is undesirable,
because you're having e.g. a REST API listening on /api/*
or a websocket endpoint listening on
/push/*
, then you can configure them as an exclude pattern as below:
<context-param> <param-name>org.omnifaces.FACES_VIEWS_SCAN_PATHS</param-name> <param-value>/*.xhtml/*, !/api, !/push</param-value> </context-param>
JSF normally inspects the request URI to derive a logical view id from it. It assumes the FacesServlet is either mapped on a prefix path or an extension, and will get confused when an extensionless "exactly mapped" request is encountered. To counter this, FacesViews makes use of a filter that intercepts each request and makes it appear to JSF that the request was a normal extension mapped one.
In order to do this dispatching, two methods are provided; forwarding, and wrapping the request and continuing the
filter chain. For the last method to work, the FacesServlet is programmatically mapped to every individual resource
(page/view) that is encountered. By default the filter is automatically registered and is inserted after all
filters that are declared in web.xml
.
These internal details are important for users to be aware of, since they greatly influence how extensionless requests interact with other filter based functionality such as security filters, compression filters, file upload filters, etc.
With the forwarding method, filters typically have to be set to dispatch type FORWARD
as well. If the
FacesViews filter is the first in the chain other filters that are set to dispatch type REQUEST
will
NOT be invoked at all (the chain is ended). If the FacesViews filter is set to be the last, other
filters will be invoked, but they should not modify the response (a forward clears the response buffer till so far
if not committed).
No such problems appear to exist when the FacesViews filter simply continues the filtering chain. However, since it wraps the requess there might be unforeseen problems with containers or other filters that get confused when the request URI changes in the middle of the chain. Continuing the chain has been tested with JBoss EAP 6.0.1, GlassFish 3.1.2.2, WebLogic 12.1.1 and TomEE 1.5.2-snapshot and thus with both Mojarra and MyFaces. However, since it's a new method for OmniFaces 1.4 we kept the existing forward as an alternative.
The configuration options below provide more details about the dispatch methods and the filter position which can be used for tweaking FacesViews for interoperability with other filters.
The following context parameters are available.
"org.omnifaces.FACES_VIEWS_ENABLED" |
Used to completely switch scanning off.
Allowed values: { true ,false }
Default value: true
(note that if no /WEB-INF/faces-views directory is present and no explicit paths have been configured, no scanning will be done either) |
"org.omnifaces.FACES_VIEWS_SCAN_PATHS" |
A comma separated list of paths that are to be scanned in addition to /WEB-INF/faces-views .
Allowed values: any path relative to the web root, including the root path ( / ) and /WEB-INF .
A wildcard can be added to the path, which will cause only files with the given extension te be scanned.
Examples: - Scan all files in both folder1 and folder2: /folder1, /folder2
- Scan only .xhtml files in the root: /*.xhtml
Note that when the root path is given, all its sub paths are also scanned EXCEPT WEB-INF , META-INF and resources .
If those have to be scanned as well, they can be added to the list of paths explicitly.
Default value: /WEB-INF/faces-views (note when this value is set, those paths will be in addition to the default /WEB-INF/faces-views )
|
"org.omnifaces.FACES_VIEWS_SCANNED_VIEWS_ALWAYS_EXTENSIONLESS" |
Used to set how scanned views should be rendered in JSF controlled links.
With this setting set to false , it depends on whether the request URI uses an extension or not.
If it doesn't, links are also rendered without one, otherwise they are rendered with an extension.
When set to true links are always rendered without an extension.
Default value: true
|
"org.omnifaces.FACES_VIEWS_EXTENSION_ACTION" |
Determines the action that is performed whenever a resource is requested WITH extension that's also available without an extension.
Allowed values are enumerated in ExtensionAction , which have the following meaning:
- REDIRECT_TO_EXTENSIONLESS : Send a 301 (permanent) redirect to the same URL, but with the extension removed. E.g. /foo.xhtml redirects to /foo .
- SEND_404 : Send a 404 (not found), makes it look like e.g. /foo.xhtml never existed and there's only /foo .
- PROCEED : No special action is taken. Both /foo.xhtml and /foo are processed as-if they were separate views (with same content).
Default value: REDIRECT_TO_EXTENSIONLESS
|
"org.omnifaces.FACES_VIEWS_PATH_ACTION" |
Determines the action that is performed whenever a resource is requested in a public path that has been used for scanning views by faces views
(e.g. the paths set by "org.omnifaces.FACES_VIEWS_SCAN_PATHS" , but excluding the root path /).
Allowed values are enumerated in PathAction , which have the following meaning:
- SEND_404 : Send a 404 (not found), makes it look like e.g. /path/foo.xhtml never existed and there's only /foo and optionally /foo.xhtml .
- REDIRECT_TO_SCANNED_EXTENSIONLESS : Send a 301 (permanent) redirect to the resource corresponding with the one that was scanned. E.g. /path/foo.xml redirects to /foo .
- PROCEED : No special action is taken. /path/foo.xml and /foo (and optionally /foo.xhtml ) will be accessible.
Default value: SEND_404
|
"org.omnifaces.FACES_VIEWS_FILTER_AFTER_DECLARED_FILTERS" |
Used to set whether the FacesViewsForwardingFilter should match before declared filters (false ) or
after declared filters (true ).
Default value: false (the FacesViews forwarding filter is the first in the filter chain)
|
Since OmniFaces 2.0, Servlet 2.5 compatibility has been dropped. Servlet 2.5 users are advised to either upgrade to Servlet 3.0+, or keep using OmniFaces 1.x.
In OmniFaces 1.4, a major overhaul was done for FacesViews and several things are done differently from how they were done in 1.3
Most notably is that the FacesServlet dispatch changed from forwarding to continuing the chain, the FacesViews filter moved from being the first in the chain to being the last, links are always rendered as their extensionless variant independent of the request using an extension or not, and when a request with an extension is used anyway (e.g. by typing it directly into the address bar) it's now redirected to the extensionless variant.
By putting the following settings in web.xml
a behavior that most closely resembles 1.3 can be obtained:
<context-param> <param-name>org.omnifaces.FACES_VIEWS_DISPATCH_METHOD</param-name> <param-value>FORWARD</param-value> </context-param> <context-param> <param-name>org.omnifaces.FACES_VIEWS_SCANNED_VIEWS_ALWAYS_EXTENSIONLESS</param-name> <param-value>false</param-value> </context-param> <context-param> <param-name>org.omnifaces.FACES_VIEWS_EXTENSION_ACTION</param-name> <param-value>PROCEED</param-value> </context-param>
Copyright © 2012–2018 OmniFaces. All rights reserved.