
org.omnifaces.facesviews.package-info Maven / Gradle / Ivy
/*
* Copyright OmniFaces
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
/**
*
* This package contains the classes for the OmniFaces FacesViews feature.
*
*
Introduction
*
*
* 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 {@link jakarta.faces.webapp.FacesServlet} in web.xml
for
* the .xhtml
to .xhtml
mapping.
*
*
Example 1:
*
*
* 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
* {@link jakarta.faces.webapp.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.
*
*
Example 2:
*
*
* 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.
*
*
Example 3:
*
*
* 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 @
{@link org.omnifaces.cdi.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.
*
*
Example 3:
*
*
* 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/*
.
*
*
*
Welcome files
*
*
* 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 https://example.com
will redirect to say
* https://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>
*
*
*
* Dispatch methods
*
*
* 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.
*
*
Configuration
*
*
* The following context parameters are available.
*
*
All available context parameters
*
*
* {@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_ENABLED_PARAM_NAME}
* 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)
*
*
*
* {@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_SCAN_PATHS_PARAM_NAME}
* 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
)
*
*
*
*
* {@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_SCANNED_VIEWS_EXTENSIONLESS_PARAM_NAME}
* 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
*
*
*
*
* {@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_EXTENSION_ACTION_PARAM_NAME}
* 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 {@link org.omnifaces.facesviews.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
*
*
*
*
* {@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_PATH_ACTION_PARAM_NAME}
* 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 {@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_SCAN_PATHS_PARAM_NAME}
, but excluding the root path /).
*
Allowed values are enumerated in {@link org.omnifaces.facesviews.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
*
*
*
*
* {@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_FILTER_AFTER_DECLARED_FILTERS_PARAM_NAME}
* Used to set whether the {@link org.omnifaces.facesviews.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)
*
*
*
*
*
*
* @author Arjan Tijms
*/
package org.omnifaces.facesviews;