<anyxmlelement xmlns:o="omnifaces"/>
| Info | Value |
|---|---|
| ID (tag prefix) | o |
| URI | omnifaces |
| Tag | Description | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| cache |
The Caching can take place in application scope, or in session scope. For individual fragments a time can be specified for which the cached content is valid. After this time is elapsed, the very first request to the page containing the cache component in question will cause new content to be rendered and put into the cache. A default time can be set per scope in web.xml. For each scope a maximum capacity can be set. If the capacity for that scope is exceeded, an element will be removed following a least recently used policy (LRU).
Via a cache provider mechanism an alternative cache implementation can be configured in web.xml. The default
cache is based on Setting a custom caching provider
A custom caching provider can be set by using the
<context-param>
<param-name>org.omnifaces.CACHE_PROVIDER</param-name>
<param-value>com.example.MyProvider</param-value>
</context-param>
The default provider, Global settings
For the default provider, the maximum capacity and the default time to live can be specified for the
supported scopes "session" and "application". If the maximum capacity is reached, an entry will be
evicted following a least recently used policy. The default time to live specifies for how long
entries are considered to be valid. A value for the
|
|||||||||||||||||||||||||||
| cacheValue | CacheValue is a replacement for ui:param and c:set that only evaluates a value expression once
and thereafter resolves it from the cache.
A |
|||||||||||||||||||||||||||
| componentIdParam |
The Components can be identified via both their client id or simple component id. Via the former it's possible to e.g. render only a specific row in a table. For specific cases, it's possible to render only the parent component and omit any children. Among the use cases for this is creating simple mashups from various Faces based views, and scripts needing to obtain markup for specific components on an initial (non-faces) request. Note that this is a rather specialized component and for many common use cases the user is advised to investigate if the existing AJAX and partial page requests in Faces don't already cover the requirements. For the moment this component only supports the direct output of the original markup and does not wrap it into any "partial response" envelope. |
|||||||||||||||||||||||||||
| compositeConverter |
The Usage
This converter is available by
<h:inputText value="#{bean.value}">
<o:compositeConverter converterIds="trimConverter, sanitizeConverter, entityConverter" />
</h:inputText>
Execution Order
The converters are executed in the order they are defined in the
|
|||||||||||||||||||||||||||
| conditionalComment |
The
<!--[if lte IE 7]>
<link rel="stylesheet" href="ie6-ie7.css" />
<![endif]-->
However, Facelets renders the comment's contents HTML-escaped which makes it unusable.
<!--[if lte IE 7]>
<link rel="stylesheet" href="ie6-ie7.css" />
<![endif]-->
Also, if
<h:outputText
value="<!--[if lte IE 7]><link rel="stylesheet" href="ie6-ie7.css" /><![endif]-->"
escape="false" />
This component is designed to solve this problem.
<o:conditionalComment if="lte IE 7">
<link rel="stylesheet" href="ie6-ie7.css" />
</o:conditionalComment>
Note that you cannot use this with |
|||||||||||||||||||||||||||
| converter |
The Usage
When you specify for example the standard
<o:converter converterId="jakarta.faces.DateTime" pattern="#{item.pattern}" locale="#{item.locale}" />
The converter ID of all standard Faces converters can be found in
their javadocs.
First go to the javadoc of the class of interest, then go to JSF 2.3 compatibility
The |
|||||||||||||||||||||||||||
| criticalStylesheet |
The Usage
Just use it the same way as a <o:criticalStylesheet library="yourlibrary" name="scripts/filename.js" /> You can even explicitly configure third-party stylesheet resources to be loaded this way, such as PrimeFaces stylesheets. <o:criticalStylesheet library="primefaces" name="components.css" /> <o:criticalStylesheet library="primefaces" name="layout.css" /> |
|||||||||||||||||||||||||||
| deferredScript |
The
This will give bonus points with among others the Google PageSpeed tool, on the contrary to placing the script at
bottom of body, or using
Since 2.4 this will render the Usage
Just use it the same way as a <o:deferredScript library="yourlibrary" name="scripts/filename.js" />
You can use the optional |
|||||||||||||||||||||||||||
| enableRestorableView |
The
There are however technical design limitations: the recreated view is exactly the same as during the initial
request. In other words, the view has lost its state. Any modifications which were made after the original initial
request, either by taghandlers or (ajax) conditionally rendered components based on some view or even session
scoped variables, are completely lost. Thus, the view should be designed that way that it can be used with a request
scoped bean. You can use it with a view scoped bean, but then you should add a Usage
To enable the restorable view, just add the
<f:metadata>
<o:enableRestorableView/>
</f:metadata>
Mojarra's new stateless mode
Since Mojarra 2.1.19, about 2 months after OmniFaces introduced the
<f:view transient="true">
...
</f:view>
This goes actually a step further than |
|||||||||||||||||||||||||||
| form |
The
Additionally, it offers in combination with the
Since version 2.1 this component also supports adding query string parameters to the action URL via nested
Since version 3.0, it will also during ajax requests automatically send only the form data which actually need to
be processed as opposed to the entire form, based on the
You can use it the same way as Use request URI
This was available since version 1.6, but since version 3.0, this has become enabled by default. So just using
<o:form useRequestURI="false"> Include request params
When you want to include request parameters only instead of the entire request URI with query string, set the
<o:form includeRequestParams="true"> Partial submit
This is the default behavior. So just using <o:form partialSubmit="false"> Add query string parameters to action URL
The standard
<o:form>
<f:param name="somename" value="somevalue" />
...
</o:form>
The The support was added in OmniFaces 2.2. Ignore Validation Failed
In order to properly use the |
|||||||||||||||||||||||||||
| genericEnumConverter |
The
This can be solved by using a
@FacesConverter("roleConverter")
public class RoleConverter extends EnumConverter {
public RoleConverter() {
super(Role.class);
}
}
<h:selectManyCheckbox value="#{bean.selectedRoles}" converter="roleConverter">
<f:selectItems value="#{bean.availableRoles}" />
</h:selectManyCheckbox>
However, creating a new converter for every single enum type, only and only for use in Usage
This converter is available by converter ID
<h:selectManyCheckbox value="#{bean.selectedEnums}" converter="omnifaces.GenericEnumConverter">
<f:selectItems value="#{bean.availableEnums}" />
</h:selectManyCheckbox>
Since OmniFaces 4.5 it's also available by
<h:selectManyCheckbox value="#{bean.selectedEnums}">
<f:selectItems value="#{bean.availableEnums}" />
<o:genericEnumConverter />
</h:selectManyCheckbox>
See also:
JSF 2.3This converter is not necessary anymore since JSF 2.3 thanks to the fixes in issue 1422.
<h:selectManyCheckbox value="#{bean.selectedEnums}">
<f:selectItems value="#{bean.availableEnums}" />
</h:selectManyCheckbox>
However, when you're having an input component without a value attribute, and thus the exact type cannot be automatically determined by simply inspecting the return type of the associated getter method, then this converter may be still useful.
<h:selectManyCheckbox converter="omnifaces.GenericEnumConverter">
<f:selectItems value="#{bean.availableEnums}" />
</h:selectManyCheckbox>
|
|||||||||||||||||||||||||||
| graphicImage |
The Data URI
Set
<o:graphicImage name="icon.png" dataURI="true" /> <!-- Faces resource as data URI -->
<o:graphicImage value="#{bean.icon}" dataURI="true" /> <!-- byte[]/InputStream property as data URI -->
This basically renders the image inline in HTML output immediately during Faces render response phase. This approach is very useful for a "preview" feature of uploaded images and works also in combination with view scoped beans. This approach is however not recommended for "permanent" and/or "large" images as it doesn't offer the browser any opportunity to cache the images for reuse, ~10KB would typically be the max even less so if there are more such images on the same page. Image streaming
When not rendered as data URI, the
@Named
@RequestScoped
public class Bean {
private List<Image> images; // Image class should NOT have "content" property, or at least it be lazy loaded.
@Inject
private ImageService service;
@PostConstruct
public void init() {
images = service.list();
}
public List<Image> getImages() {
return images;
}
}
@GraphicImageBean
public class Images {
@Inject
private ImageService service;
public byte[] get(Long id) {
return service.getContent(id);
}
}
<ui:repeat value="#{bean.images}" var="image">
<o:graphicImage value="#{images.get(image.id)}" />
</ui:repeat>
A
In case the property is a method expression taking arguments, each of those arguments will be converted to a string
HTTP request parameter and back to actual objects using the converters registered by class as available via
Caching
In case your "image" entity supports it, you can also supply the "last modified" property which will be used in the
<ui:repeat value="#{bean.images}" var="image">
<o:graphicImage value="#{images.get(image.id)}" lastModified="#{image.lastModified}" />
</ui:repeat>
When unspecified, then the "default resource maximum age" as set in either the Mojarra specific context parameter
Image types
When rendered as data URI, the content type will be guessed based on content header. So far, WEBP, JPEG, PNG, GIF, ICO,
SVG, BMP and TIFF are recognized. If the content header is unrecognized, or when the image is rendered as regular
image source, then the content type will default to
<o:graphicImage value="#{images.get(image.id)}" type="svg" />
The content type will be resolved via
<mime-mapping>
<extension>svg</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
SVG view modes
When serving a SVG image, you can use
<o:graphicImage value="#{images.get(image.id)}" type="svg" fragment="svgView(viewBox(0,50,200,200))" />
Lazy loading
Since OmniFaces 3.10, you can set the <o:graphicImage ... lazy="true" />
This attribute is ignored when the Design notesThe bean class name and method name will end up in the image source URL. Although this is technically harmless and not tamperable by hackers, you might want to choose a "sensible" class and method name for this purpose.
Like |
|||||||||||||||||||||||||||
| hashParam |
The
The "hash query string" is the part in URL after the https://example.com/page.xhtml#foo=baz&bar=kaz
This specific part of the URL (also called hash fragment identifier) is by default not sent to the server. This
component will on page load and on every Usage
It's very similar to the
<f:metadata>
<o:hashParam name="foo" value="#{bean.foo}" />
<o:hashParam name="bar" value="#{bean.bar}" />
</f:metadata>
You can use the
<f:metadata>
<o:hashParam name="foo" value="#{bean.foo}" render="fooResult" />
<o:hashParam name="bar" value="#{bean.bar}" />
</f:metadata>
...
<h:body>
...
<h:panelGroup id="fooResult">
...
</h:panelGroup>
...
</h:body>
In case you need to invoke a bean method before rendering, e.g. to preload the rendered contents based on new hash
param values, then you can observe the
You can use the
<f:metadata>
<o:hashParam name="foo" value="#{bean.foo}" />
<o:hashParam name="bar" value="#{bean.bar}" default="kaz" />
</f:metadata>
When
Note that as it extends from the standard Events
When the hash query string is changed by the client side, e.g. by following a
public void onHashChange(@Observes HashChangeEvent event) {
String oldHashString = event.getOldValue();
String newHashString = event.getNewValue();
// ...
}
This is useful in case you want to preload the model for whatever is rendered by
|
|||||||||||||||||||||||||||
| highlight |
The
<h:form>
<h:inputText value="#{bean.input1}" required="true" />
<h:inputText value="#{bean.input2}" required="true" />
<h:commandButton value="Submit" action="#{bean.submit}" />
</h:form>
<o:highlight />
The default error style class name is
label.error {
color: #f00;
}
input.error, select.error, textarea.error {
background-color: #fee;
}
You can override the default error style class by the <o:highlight styleClass="invalid" />
You can disable the default focus on the first invalid input element setting the <o:highlight styleClass="invalid" focus="false" /> Since version 2.5, the error style class will be removed from the input element and its associated label when the enduser starts using the input element. |
|||||||||||||||||||||||||||
| ignoreValidationFailed |
The UsageFor example:
<o:form>
...
<h:commandButton value="save valid data" action="#{bean.saveValidData}">
<o:ignoreValidationFailed />
<f:ajax execute="@form" />
</h:commandButton>
</o:form>
Note that the model values will (obviously) only be updated for components which have actually passed the validation.
Also the validation messages will still be displayed. If you prefer to not display them, then you'd need to exclude
them from rendering by |
|||||||||||||||||||||||||||
| implicitNumberConverter | This converter won't output the percent or currency symbols, that's up to the UI. This converter will implicitly infer percent or currency symbols on submitted value when absent, just to prevent an unnecessary conversion error. Usage
This converter is available by converter ID
<span class="currency">
<span class="symbol">$</span>
<h:inputText value="#{bean.price}">
<o:converter converterId="omnifaces.ImplicitNumberConverter" type="currency" currencySymbol="$" />
</h:inputText>
</span>
Since OmniFaces 4.5 it's also available by
<span class="currency">
<span class="symbol">$</span>
<h:inputText value="#{bean.price}">
<o:implicitNumberConverter type="currency" currencySymbol="$" />
</h:inputText>
</span>
|
|||||||||||||||||||||||||||
| importConstants |
The UsageFor example:
public class Foo {
public static final String FOO1 = "foo1";
public static final String FOO2 = "foo2";
}
public interface Bar {
public String BAR1 = "bar1";
public String BAR2 = "bar2";
}
public enum Baz {
BAZ1, BAZ2;
}
public enum Faz implements Bar {
FAZ1, FAZ2;
}
The constant field values of the above types can be mapped into the request scope as follows:
<o:importConstants type="com.example.Foo" />
<o:importConstants type="com.example.Bar" />
<o:importConstants type="com.example.Baz" var="Bazzz" />
<o:importConstants type="com.example.Faz" />
...
#{Foo.FOO1}, #{Foo.FOO2}, #{Bar.BAR1}, #{Bar.BAR2}, #{Bazzz.BAZ1}, #{Bazzz.BAZ2}, #{Faz.FAZ1}, #{Faz.BAR2}
...
<h:selectOneMenu>
<f:selectItems value="#{Faz.values()}" /> <!-- FAZ1, FAZ2, BAR1, BAR2 -->
</h:selectOneMenu>
The map is by default stored in the request scope by the simple name of the type as variable name. You can override
this by explicitly specifying the
The resolved constants are by reference stored in the cache to improve retrieving performance. There is also a
runtime (no, not compiletime as that's just not possible in EL) check during retrieving the constant value.
If a constant value doesn't exist, then an
Since version 4.3, you can use the
Since version 4.6, when the class specified in the
<h:selectOneMenu>
<f:selectItems value="#{Faz.members()}" /> <!-- FAZ1, FAZ2 -->
</h:selectOneMenu>
JSF 2.3
JSF 2.3 also offers a |
|||||||||||||||||||||||||||
| importFunctions |
The UsageFor example:
<o:importFunctions type="java.lang.Math" var="m" />
...
#{m:abs(-10)}
#{m:max(bean.number1, bean.number2)}
The functions prefix becomes by default the simple name of the type. You can override this by explicitly
specifying the The resolved functions are by reference stored in the cache to improve retrieving performance. Precaution as to multiple functions with exactly the same method name
EL functions does not support method overloading. It's therefore not possible to
provide overloaded methods like If there are multiple function methods discovered with exactly the same name, then the one with the least amount of parameters will be used. If there are multiple function methods with exactly the same name and amount of parameters, then the choice is unspecified (technically, JVM-dependent, the first one in the methods array as found by reflection would be picked up) and should not be relied upon. So if you absolutely need to differentiate functions in such case, give them each a different name.
Since version 4.3, you can use the Design notes
Note that the colon |
|||||||||||||||||||||||||||
| inputFile |
The Usage
You can use it the same way as Single file selection
It is basically not different from
<h:form enctype="multipart/form-data">
<o:inputFile value="#{bean.file}" />
<h:commandButton value="Upload" action="#{bean.upload}" />
</h:form>
private Part file; // +getter+setter
public void upload() {
if (file != null) {
var name = Servlets.getSubmittedFileName(file);
var type = file.getContentType();
var size = file.getSize();
var content = file.getInputStream();
// ...
}
}
Note that it's strongly recommended to use Multiple file selection
The
<h:form enctype="multipart/form-data">
<o:inputFile value="#{bean.files}" multiple="true" />
<h:commandButton value="Upload" action="#{bean.upload}" />
</h:form>
private List<Part> files; // +getter+setter
public void upload() {
if (files != null) {
for (var file : files) {
var name = Servlets.getSubmittedFileName(file);
var type = file.getContentType();
var size = file.getSize();
var content = file.getInputStream();
// ...
}
}
}
Folder selection
The
<h:form enctype="multipart/form-data">
<o:inputFile value="#{bean.files}" directory="true" />
<h:commandButton value="Upload" action="#{bean.upload}" />
</h:form>
private List<Part> files; // +getter+setter
public void upload() {
if (files != null) {
for (var file : files) {
var name = Servlets.getSubmittedFileName(file);
var type = file.getContentType();
var size = file.getSize();
var content = file.getInputStream();
// ...
}
}
}
Do note that this does not send physical folders, but only files contained in those folders. Media type filtering
The
<h:form enctype="multipart/form-data">
<o:inputFile id="file" value="#{bean.losslessImageFile}" accept="image/png,image/gif" />
<h:commandButton value="Upload" action="#{bean.upload}" />
<h:message for="file" />
</h:form>
<h:form enctype="multipart/form-data">
<o:inputFile id="file" value="#{bean.anyImageFile}" accept="image/*" />
<h:commandButton value="Upload" action="#{bean.upload}" />
<h:message for="file" />
</h:form>
<h:form enctype="multipart/form-data">
<o:inputFile id="file" value="#{bean.anyMediaFile}" accept="audio/*,image/*,video/*" />
<h:commandButton value="Upload" action="#{bean.upload}" />
<h:message for="file" />
</h:form>
This will also be validated in the server side using a built-in validator. Do note that the
The default message for server side validation of {0}: Media type of file ''{1}'' does not match ''{2}''
Where
You can override the default message by the
<h:form enctype="multipart/form-data">
<o:inputFile id="file" value="#{bean.anyImageFile}" accept="image/*" acceptMessage="File {1} is unacceptable!" />
<h:commandButton value="Upload" action="#{bean.upload}" />
<h:message for="file" />
</h:form>
Or by the custom message bundle file as identified by
org.omnifaces.component.input.InputFile.accept = File {1} is unacceptable!
File size validation
The <o:inputFile id="file" ... /> <h:message id="messageForFile" for="file" /> <!-- This must have 'id' attribute set! --> This way the client side can trigger Faces via an ajax request to update the message component with the client side validation message. Noted should be that the file(s) will not be sent, hereby saving network bandwidth.
<h:form enctype="multipart/form-data">
<o:inputFile id="file" value="#{bean.file}" maxsize="#{10 * 1024 * 1024}" /> <!-- 10MiB -->
<h:commandButton value="Upload" action="#{bean.upload}" />
<h:message id="messageForFile" for="file" />
</h:form>
This will also be validated in the server side using a built-in validator.
The default message for both client side and server side validation of {0}: Size of file ''{1}'' is larger than maximum of {2}
Where
You can override the default message by the
<h:form enctype="multipart/form-data">
<o:inputFile id="file" value="#{bean.file}" maxsize="#{10 * 1024 * 1024}" maxsizeMessage="File {1} is too big!" />
<h:commandButton value="Upload" action="#{bean.upload}" />
<h:message id="messageForFile" for="file" />
</h:form>
Or by the custom message bundle file as identified by
org.omnifaces.component.input.InputFile.maxsize = File {1} is too big!
|
|||||||||||||||||||||||||||
| inputHidden |
The
Use case 1: Imagine a form with a
Use case 2: Imagine a form with an
This behavior cannot be achieved by using
Also, the Usage
You can use it the same way as
<h:form>
<o:inputHidden value="#{bean.hidden}" />
...
</h:form>
When using ajax, don't forget to make sure that the component is also covered by the |
|||||||||||||||||||||||||||
| link |
The
You can use it the same way as Include request params
When you want to include request query string parameters of the current URL into the link's target URL, set the
<o:link value="Go to some page with same query string" outcome="some-page" includeRequestParams="true"> |
|||||||||||||||||||||||||||
| listConverter |
The
This converter allows you to populate a selection component with complex Java objects and have Faces convert those
automatically back without the need to provide a custom converter which may need to do the job based on possibly
expensive service/DAO operations. This converter automatically converts based on the Usage
This converter is available by converter ID
<p:pickList value="#{bean.dualListModel}" var="entity" itemValue="#{entity}" itemLabel="#{entity.someProperty}">
<o:converter converterId="omnifaces.ListConverter" list="#{bean.dualListModel.source}" />
</p:pickList>
Since OmniFaces 4.5 it's also available by
<p:pickList value="#{bean.dualListModel}" var="entity" itemValue="#{entity}" itemLabel="#{entity.someProperty}">
<o:listConverter" list="#{bean.dualListModel.source}" />
</p:pickList>
Make sure that your entity has a good
|
|||||||||||||||||||||||||||
| listIndexConverter |
The Usage
This converter is available by converter ID
<p:pickList value="#{bean.dualListModel}" var="entity" itemValue="#{entity}" itemLabel="#{entity.someProperty}">
<o:converter converterId="omnifaces.ListIndexConverter" list="#{bean.dualListModel.source}" />
</p:pickList>
Since OmniFaces 4.5 it's also available by
<p:pickList value="#{bean.dualListModel}" var="entity" itemValue="#{entity}" itemLabel="#{entity.someProperty}">
<o:listIndexConverter" list="#{bean.dualListModel.source}" />
</p:pickList>
Pros and cons as compared to
|
|||||||||||||||||||||||||||
| loadBundle |
The
You can use the
The locale of the resource bundle is obtained as specified in Usage
You can use it the same way as |
|||||||||||||||||||||||||||
| massAttribute |
The <o:massAttribute> sets an attribute of the given name and value on all nested components,
if they don't already have an attribute set. On boolean attributes like UsageFor example, the following setup
<o:massAttribute name="disabled" value="true">
<h:inputText id="input1" />
<h:inputText id="input2" disabled="true" />
<h:inputText id="input3" disabled="false" />
<h:inputText id="input4" disabled="#{true}" />
<h:inputText id="input5" disabled="#{false}" />
</o:massAttribute>
will set the disabled="true" attribute in input1, input2 and
input3 as those are the only components without a value expression on the boolean attribute.
As another general example without booleans, the following setup
<o:massAttribute name="styleClass" value="#{component.valid ? '' : 'error'}">
<h:inputText id="input1" />
<h:inputText id="input2" styleClass="some" />
<h:inputText id="input3" styleClass="#{'some'}" />
<h:inputText id="input4" styleClass="#{null}" />
</o:massAttribute>
will only set the styleClass="#{component.valid ? '' : 'error'}" attribute in input1 as
that's the only component on which the attribute is absent.
Do note that the specified EL expression will actually be evaluated on a per-component basis.
To target a specific component (super)class, use the
<o:massAttribute name="styleClass" value="#{component.valid ? '' : 'error'}" target="jakarta.faces.component.UIInput">
<h:outputLabel for="input1" />
<h:inputText id="input1" />
<h:outputLabel for="input2" />
<h:inputText id="input2" />
<h:outputLabel for="input3" />
<h:inputText id="input3" />
</o:massAttribute>
Since OmniFaces 3.10, the |
|||||||||||||||||||||||||||
| messages |
The Multiple
|
|||||||||||||||||||||||||||
| methodParam |
The This handler wraps a value expression that's actually a method expression by another value expression that returns a method expression that gets the value of first value expression, which as "side-effect" executes the original method expression. This somewhat over-the-top chain of wrapping is done so a method expression can be passed as attribute into a Facelet tag. |
|||||||||||||||||||||||||||
| moveComponent |
The The destination of a move operation is specified in terms of a location that's relative to a given target component. The following shows a list of supported destinations:
|
|||||||||||||||||||||||||||
| notification |
The Prerequisites
This component requires the
<link rel="manifest" href="#{resource['omnifaces:manifest.webmanifest']}" />
The browser notification permission must be requested via a user gesture before any notification can be shown: <button type="button" onclick="OmniFaces.Notification.requestPermission()">Enable Notifications</button>
The CDI backing bean must have at least one Basic Usage
Declare the <o:notification channel="notifications" />
In the server side, inject the push context and send notification messages created via
@Inject @Push(type=NOTIFICATION)
private PushContext notifications;
public void sendNotification() {
notifications.send(Notification.createNotificationMessage("Order shipped", "Your order #1234 has been shipped."));
}
You can also add a URL so that clicking the notification will navigate to it:
notifications.send(Notification.createNotificationMessage("Order shipped", "Your order has been shipped.", "https://example.com/orders/1234"));
Relative URLs are also accepted:
notifications.send(Notification.createNotificationMessage("Order shipped", "Your order has been shipped.", "/orders/1234"));
User-targeted Notifications
The optional
<o:notification channel="notifications" user="#{request.remoteUser}" />
The notification can then be sent to a specific user:
notifications.send(Notification.createNotificationMessage("New message", "You have a new message."), recipientUserId);
Display behavior
By default, each new notification replaces the previous one from the same component. To let notifications stack
independently instead, set the <o:notification channel="notifications" stacked="true" />
The <o:notification channel="alerts" requireInteraction="true" />
The <o:notification channel="updates" silent="true" /> Event Handlers
The <o:notification channel="notifications" onclick="handleClick" onclose="handleClose" />
The event's
function handleClick(event) {
console.log("Channel: " + event.detail.data.channel);
console.log("URL (if any): " + event.detail.data.url);
console.log("Tag (if not stacked): " + event.detail.tag);
}
function handleClose(event) {
console.log("Channel: " + event.detail.data.channel);
console.log("Tag (if not stacked): " + event.detail.tag);
}
When you need to invoke a server-side action on notification click, use
<o:notification channel="notifications" onclick="handleNotificationClick" />
<h:form>
<h:commandScript name="markAsRead" action="#{notificationBean.markAsRead}" />
</h:form>
With this handler:
function handleNotificationClick(event) {
markAsRead({ "notification.url": event.detail.data?.url });
}
And this bean:
public void markAsRead() {
var url = Faces.getRequestParameter("notification.url");
// ...
}
JavaScript API
The current permission can be checked via const notificationPermission = OmniFaces.Notification.getPermission();
You can use
OmniFaces.Notification.show("notifications", "Please wait ...");
OmniFaces.Notification.show("notifications", "Hello!", "This is a notification.");
OmniFaces.Notification.show("notifications", "Click me!", "Opens a link.", "https://omnifaces.org");
Platform limitations
The
<o:notification channel="alerts" icon="#{resource['icons/alert.png']}" />
|
|||||||||||||||||||||||||||
| onloadScript |
The You can put it anywhere in the view, it will always be relocated to the end of body.
<o:onloadScript>alert('OnloadScript is invoked!');</o:onloadScript>
The |
|||||||||||||||||||||||||||
| outputFormat |
The
You can use it the same way as
<o:outputFormat value="#{i18n['link.title']}" var="_link_title">
<f:param value="#{bean.foo}" />
<f:param value="#{bean.bar}" />
</o:outputFormat>
<h:commandLink value="#{i18n['link.value']}" title="#{_link_title}" />
<o:outputFormat value="#{bean.number}" var="_percentage">
<f:convertNumber type="percent" />
</o:outputFormat>
<div title="Percentage: #{_percentage}" />
Make sure that the |
|||||||||||||||||||||||||||
| outputLabel |
The
You can use it the same way as |
|||||||||||||||||||||||||||
| param |
The
You can use it the same way as
Also, if no value is specified, but children are present, then the encoded output of children will be returned as
param value. This is useful when you want to supply Faces components or HTML as parameter of an unescaped
<h:outputFormat value="#{bundle.paragraph}" escape="false">
<o:param><h:link outcome="contact" value="#{bundle.contact}" /></o:param>
</h:outputFormat>
with this bundle
paragraph = Please {0} for more information.
contact = contact us
will result in the link being actually encoded as output format parameter value. |
|||||||||||||||||||||||||||
| pathParam | The <o:pathParam> is a component that extends the OmniFaces Param to support
MultiViews feature of FacesViews. It is done by rendering the supplied parameters of such components
as <h:link> and <h:button> among others as path parameters and not as
query parameters as otherwise will be produced by <o:param> and <f:param> tags.
The component has built-in support for a
This component doesn't support returning encoded output of its children as parameter value in case no value is present.
This feature is provided by Also, the name attribute must not be specified for this component as it already evaluates to a predefined one.
This component is used to create bookmarkable URLs via standard outcome target components that take into account
In the following example the link to the multi view page will be rendered with two path parameters:
<h:link value="Link" outcome="multiview-supported-path">
<o:pathParam value="first" />
<o:pathParam value="second" />
</h:link>
The code above will be rendered as:
<a id="..." name="..." href="/context-path/multiview-supported-path/first/second">Link</a>.
The path parameters will be available via @Inject @Param(pathIndex=0) private String first; and
@Inject @Param(pathIndex=1) private String second; the usual way. |
|||||||||||||||||||||||||||
| requiredCheckboxValidator |
The
As for every other Usage
This validator is available by validator ID
<h:selectBooleanCheckbox id="agree" value="#{bean.agree}" requiredMessage="You must agree!">
<f:validator validatorId="omnifaces.RequiredCheckboxValidator" />
</h:selectBooleanCheckbox>
Since OmniFaces 4.5 it's also available by
<h:selectBooleanCheckbox id="agree" value="#{bean.agree}" requiredMessage="You must agree!">
<o:requiredCheckboxValidator" />
</h:selectBooleanCheckbox>
The validator will use the message as specified in {0}: a tick is required" |
|||||||||||||||||||||||||||
| resolveComponent |
The |
|||||||||||||||||||||||||||
| resourceInclude |
The Note that this isn't recommended as a lasting solution, but it might ease a migration from legacy JSP with smelly scriptlets and all on them to a more sane and modern Facelets application. |
|||||||||||||||||||||||||||
| scriptErrorHandler |
The Usage (client)
Just put the component in the
<h:head>
<o:scriptErrorHandler />
</h:head>
This will register <o:scriptErrorHandler ignoreSelector="body.errorPage" /> Usage (server)
Create a CDI bean (typically application scoped) that observes the
@ApplicationScoped
public class ScriptErrorObserver {
private static final Logger logger = Logger.getLogger(ScriptErrorObserver.class.getName());
public void onScriptError(@Observes ScriptError error) {
logger.warning(error.toString());
}
}
The
Deduplication
To prevent flooding the server with repeated errors (e.g. from a |
|||||||||||||||||||||||||||
| scriptParam |
The Usage
It's similar to the
<f:metadata>
<o:scriptParam script="new Date().getTimezoneOffset()" value="#{bean.clientTimeZoneOffset}" />
<o:scriptParam script="window.screen.width" value="#{bean.clientScreenWidth}" />
<o:scriptParam script="someFunctionName()" value="#{bean.resultOfSomeFunctionName}" />
</f:metadata>
You can use the
<f:metadata>
<o:scriptParam script="foo()" value="#{bean.resultOfFoo}" render="fooResult" />
</f:metadata>
...
<h:body>
...
<h:panelGroup id="fooResult">
<ui:fragment rendered="#{not empty bean.resultOfFoo}">
The result of foo() script is: #{bean.resultOfFoo}
</ui:fragment>
</h:panelGroup>
...
</h:body>
Note that as it extends from the standard
<f:metadata>
<o:scriptParam script="window.navigator" value="#{bean.clientNavigator}" />
</f:metadata>
With a clientNavigator being an instance of jakarta.json.JsonObject:
private JsonObject clientNavigator;And this converter:
package com.example;
import java.io.StringReader;
import jakarta.faces.component.UIComponent;
import jakarta.faces.context.FacesContext;
import jakarta.faces.convert.Converter;
import jakarta.faces.convert.ConverterException;
import jakarta.faces.convert.FacesConverter;
import jakarta.json.Json;
import jakarta.json.JsonObject;
@FacesConverter(forClass = JsonObject.class)
public class JsobObjectConverter implements Converter<JsonObject> {
@Override
public String getAsString(FacesContext context, UIComponent component, JsonObject modelValue) {
if (modelValue == null) {
return "";
}
return modelValue.toString();
}
@Override
public JsonObject getAsObject(FacesContext context, UIComponent component, String submittedValue) {
if (submittedValue == null || submittedValue.isEmpty()) {
return null;
}
try {
return Json.createReader(new StringReader(submittedValue)).readObject();
}
catch (Exception e) {
throw new ConverterException("Not a valid JSON object", e);
}
}
}
Events
When the script params have been set, then any method with the
@PostScriptParam
public void initScriptParams() {
// ...
}
This is useful in case you want to preload the model for whatever is rendered by
|
|||||||||||||||||||||||||||
| selectItemGroups |
The Usage
Below example assumes a
<h:selectOneMenu value="#{bean.selectedProduct}" converter="omnifaces.SelectItemsConverter">
<f:selectItem itemValue="#{null}" />
<o:selectItemGroups value="#{bean.categories}" var="category" itemLabel="#{category.name}">
<f:selectItems value="#{category.products}" var="product" itemLabel="#{product.name}" />
</o:selectItemGroups>
</h:selectOneMenu>
|
|||||||||||||||||||||||||||
| selectItemsConverter |
The Usage
This converter is available by converter ID
<h:selectOneMenu value="#{bean.selectedItem}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>
Since OmniFaces 4.5 it's also available by
<h:selectOneMenu value="#{bean.selectedItem}">
<f:selectItems value="#{bean.availableItems}" />
<o:selectItemsConverter />
</h:selectOneMenu>
Make sure that your entity has a good
|
|||||||||||||||||||||||||||
| selectItemsIndexConverter |
The Usage
This converter is available by converter ID
<h:selectOneMenu value="#{bean.selectedItem}" converter="omnifaces.SelectItemsIndexConverter">
<f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>
Since OmniFaces 4.5 it's also available by
<h:selectOneMenu value="#{bean.selectedItem}">
<f:selectItems value="#{bean.availableItems}" />
<o:selectItemsIndexConverter />
</h:selectOneMenu>
Pros and cons as compared to
|
|||||||||||||||||||||||||||
| sitemapUrl |
The
This component is largely based off the Values
You can supply the sitemap URL via either the Domain
When the target URL is specified as
Valid formats and values for
The Request parameters
You can add query string parameters to the URL via nested Usage
Usage example of
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:ui="jakarta.faces.facelets"
xmlns:o="omnifaces"
>
<ui:repeat value="#{sitemapBean.products}" var="product">
<o:sitemapUrl viewId="/product.xhtml" lastModified="#{product.lastModified}" changeFrequency="weekly" priority="1.0">
<o:param name="id" value="#{product}" converter="productConverter" />
</o:sitemapUrl>
</ui:repeat>
</urlset>
|
|||||||||||||||||||||||||||
| skipValidators |
The UsageFor example, when adding a new row to the data table, you'd like to not immediately validate all empty rows.
<h:form>
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:inputText value="#{item.value}" required="true" />
</h:column>
</h:dataTable>
<h:commandButton value="add new row" action="#{bean.add}">
<o:skipValidators />
</h:commandButton>
<h:commandButton value="save all data" action="#{bean.save}" />
<h:messages />
</h:form>
Note that converters will still run and that model values will still be updated. This behavior is by design. |
|||||||||||||||||||||||||||
| socket |
The Configuration
Since OmniFaces 5.2, the web socket endpoint is automatically registered when
Alternatively, if you want to explicitly enable the endpoint without using
<context-param>
<param-name>org.omnifaces.SOCKET_ENDPOINT_ENABLED</param-name>
<param-value>true</param-value>
</context-param>
Usage (client)
Declare Here's an example which refers an existing JavaScript listener function (do not include the parentheses!). <o:socket channel="someChannel" onmessage="socketListener" />
function socketListener(message, channel, event) {
console.log(message);
}
Here's an example which declares an inline JavaScript listener function.
<o:socket channel="someChannel" onmessage="function(message) { console.log(message); }" />
The
In case your server is configured to run WS container on a different TCP port than the HTTP container, then you can
use the optional <o:socket port="8000" ... /> When successfully connected, the web socket is by default open as long as the document is open, and it will auto-reconnect at increasing intervals when the connection is closed/aborted as result of e.g. a network error or server restart. It will not auto-reconnect when the very first connection attempt already fails. The web socket will be implicitly closed once the document is unloaded (e.g. navigating away, close of browser window/tab, etc). In order to successfully reconnect after a server restart, or when switching to a new server node, you need to ensure that session persistence is enabled on the server. Usage (server)
In WAR side, you can inject
@Inject @Push
private PushContext someChannel;
public void sendMessage(Object message) {
someChannel.send(message);
}
By default the name of the channel is taken from the name of the variable into which injection takes place. The
channel name can be optionally specified via the @Inject @Push(channel="foo") private PushContext bar;
The message object will be encoded as JSON and be delivered as
Although web sockets support two-way communication, the Scopes and users
By default the web socket is
The optional <o:socket channel="someChannel" scope="session" ... />
The <o:socket channel="someChannel" scope="view" ... />
The
Additionally, the optional E.g. when you're using container managed authentication or a related framework/library:
<o:socket channel="someChannel" user="#{request.remoteUser}" ... />
Or when you have a custom user entity around in EL as
<o:socket channel="someChannel" user="#{someLoggedInUser.id}" ... />
When the
When the
In the server side, the push message can be targeted to the user specified in the
@Inject @Push
private PushContext someChannel;
public void sendMessage(Object message, User recipientUser) {
Long recipientUserId = recipientUser.getId();
someChannel.send(message, recipientUserId);
}
Multiple users can be targeted by passing a
public void sendMessage(Object message, Group recipientGroup) {
Collection<Long> recipientUserIds = recipientGroup.getUserIds();
someChannel.send(message, recipientUserIds);
}
Channel design hintsYou can declare multiple push channels on different scopes with or without user target throughout the application. Be however aware that the same channel name can easily be reused across multiple views, even if it's view scoped. It's more efficient if you use as few different channel names as possible and tie the channel name to a specific push socket scope/user combination, not to a specific Faces view. In case you intend to have multiple view scoped channels for different purposes, best is to use only one view scoped channel and have a global JavaScript listener which can distinguish its task based on the delivered message. E.g. by sending the message in server as below:
Map<String, Object> message = new HashMap<>();
message.put("functionName", "someFunction");
message.put("functionData", functionData); // Can be Map or Bean.
someChannel.send(message);
Which is processed in the
function someSocketListener(message) {
window[message.functionName](message.functionData);
}
function someFunction(data) {
// ...
}
function otherFunction(data) {
// ...
}
// ...
Conditionally connecting
You can use the optional
<o:socket ... connected="#{bean.pushable}" />
It defaults to
You can also explicitly set it to
<h:commandButton ... onclick="OmniFaces.Push.open('foo')">
<f:ajax ... />
</h:commandButton>
<o:socket channel="foo" scope="view" ... connected="false" />
In case you intend to have an one-time push and don't expect more messages, usually because you only wanted to
present the result of an one-time asynchronous action in a manually opened view scoped push socket as in above
example, you can optionally explicitly close the push connection from client side by invoking
function someSocketListener(message, channel) {
// ...
OmniFaces.Push.close(channel);
}
Noted should be that both ways should not be mixed. Choose either the server side way of an EL expression in
Events (client)
The optional <o:socket ... onopen="socketOpenListener" />
function socketOpenListener(channel) {
// ...
}
The
The optional <o:socket ... onerror="socketErrorListener" />
function socketErrorListener(code, channel, event) {
if (code == 1001) {
// Server has returned an unexpected response code. E.g. 503, because it's shutting down.
} else if (code == 1006) {
// Server is not reachable anymore. I.e. it's not anymore listening on TCP/IP requests.
} else {
// Any other reason which is usually not -1, 1000 or 1008, as the onclose will be invoked instead.
}
// In any case, the web socket will attempt to reconnect. This function will be invoked again.
// Once the web socket gives up reconnecting, the onclose will finally be invoked.
}
The
The optional <o:socket ... onclose="socketCloseListener" />
function socketCloseListener(code, channel, event) {
if (code == -1) {
// Web sockets not supported by client.
} else if (code == 1000) {
// Normal close (as result of expired session or view).
} else {
// Abnormal close reason (as result of an error).
}
}
The
When a session or view scoped socket is automatically closed with close reason code Events (server)
When a web socket has been opened, a new CDI
@ApplicationScoped
public class SocketObserver {
public void onOpen(@Observes @Opened SocketEvent event) {
String channel = event.getChannel(); // Returns <o:socket channel>.
Long userId = event.getUser(); // Returns <o:socket user>, if any.
// Do your thing with it. E.g. collecting them in a concurrent/synchronized collection.
// Do note that a single person can open multiple sockets on same channel/user.
}
public void onSwitch(@Observes @Switched SocketEvent event) {
String channel = event.getChannel(); // Returns <o:socket channel>.
Long currentUserId = event.getUser(); // Returns current <o:socket user>, if any.
Long previousUserId = event.getPreviousUser(); // Returns previous <o:socket user>, if any.
// Do your thing with it. E.g. updating in a concurrent/synchronized collection.
}
public void onClose(@Observes @Closed SocketEvent event) {
String channel = event.getChannel(); // Returns <o:socket channel>.
Long userId = event.getUser(); // Returns <o:socket user>, if any.
CloseCode code = event.getCloseCode(); // Returns close reason code.
// Do your thing with it. E.g. removing them from collection.
}
}
You could take the opportunity to send another push message to an application scoped socket, e.g. "User X has been logged in" (or out) when a session scoped socket is opened (or closed). Security considerationsIf the socket is declared in a page which is only restricted to logged-in users with a specific role, then you may want to add the URL of the push handshake request URL to the set of restricted URLs.
The push handshake request URL is composed of the URI prefix
<security-constraint>
<web-resource-collection>
<web-resource-name>Restrict access to role USER.</web-resource-name>
<url-pattern>/user/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>USER</role-name>
</auth-constraint>
</security-constraint>
.. and the page
<security-constraint>
<web-resource-collection>
<web-resource-name>Restrict access to role USER.</web-resource-name>
<url-pattern>/user/*</url-pattern>
<url-pattern>/omnifaces.socket/foo</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>USER</role-name>
</auth-constraint>
</security-constraint>
As extra security, particularly for those public channels which can't be restricted by security constraints, the
Business service design hints
In case you'd like to trigger a push from business service side to an application scoped push socket, then you could make use
of CDI events. First create a custom bean class representing the push event something like
public final class PushEvent {
private final String message;
public PushEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
Then use
@Inject
private BeanManager beanManager;
public void onSomeEntityChange(Entity entity) {
beanManager.getEvent().select().fire(new PushEvent(entity.getSomeProperty()));
}
Note that OmniFaces own
Finally just
@Inject @Push
private PushContext someChannel;
public void onPushEvent(@Observes PushEvent event) {
someChannel.send(event.getMessage());
}
Note that a request scoped bean wouldn't be the same one as from the originating page for the simple reason that
there's no means of a HTTP request anywhere at that moment. For exactly this reason a view and session scoped bean
would not work (as they require respectively the Faces view state and HTTP session which can only be identified by a
HTTP request). A view and session scoped push socket would also not work, so the push socket really needs to be
application scoped. The
In case the trigger in business service side is an asynchronous service method which is in turn initiated in WAR side, then
you could make use of callbacks from WAR side. Let the business service method take a callback instance as argument,
e.g. the
@Asynchronous
public void someAsyncServiceMethod(Entity entity, Consumer<Object> callback) {
// ... (some long process)
callback.accept(entity.getSomeProperty());
}
And invoke the asynchronous service method in WAR as below.
@Inject
private SomeService someService;
@Inject @Push
private PushContext someChannel;
public void someAction() {
someService.someAsyncServiceMethod(entity, message -> someChannel.send(message));
}
This would be the only way in case you intend to asynchronously send a message to a view or session scoped push
socket, and/or want to pass something from Cluster design hintsIn case your web application is deployed to a server cluster with multiple nodes, and the push event could be triggered in a different node than where the client is connected to, then it won't reach the socket. One solution is to activate and configure a JMS topic in the server configuration, trigger the push event via JMS instead of CDI, and use a JMS listener (a message driven bean, MDB) to delegate the push event to CDI. Below is an example extending on the above given business service example.
@ApplicationScoped
public class PushManager {
@Resource(lookup = "java:/jms/topic/push")
private Topic jmsTopic;
@Inject
private JMSContext jmsContext;
public void fireEvent(PushEvent pushEvent) {
try {
Message jmsMessage = jmsContext.createMessage();
jmsMessage.setStringProperty("message", pushEvent.getMessage());
jmsContext.createProducer().send(jmsTopic, jmsMessage);
}
catch (Exception e) {
// Handle.
}
}
}
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/topic/push")
})
public class PushListener implements MessageListener {
@Inject
private BeanManager beanManager;
@Override
public void onMessage(Message jmsMessage) {
try {
String message = jmsMessage.getStringProperty("message");
beanManager.fireEvent(new PushEvent(message));
}
catch (Exception e) {
// Handle.
}
}
}
Then, in your business service, instead of using
@Inject
private BeanManager beanManager;
public void onSomeEntityChange(Entity entity) {
beanManager.fireEvent(new PushEvent(entity.getSomeProperty()));
}
use the newly created
@Inject
private PushManager pushManager;
public void onSomeEntityChange(Entity entity) {
pushManager.fireEvent(new PushEvent(entity.getSomeProperty()));
}
UI update design hints
In case you'd like to perform complex UI updates, then easiest would be to put
<h:panelGroup id="foo">
... (some complex UI here) ...
</h:panelGroup>
<h:form>
<o:socket channel="someChannel" scope="view">
<f:ajax event="someEvent" listener="#{bean.pushed}" render=":foo" />
</o:socket>
</h:form>
Here, the push message simply represents the ajax event name. You can use any custom event name.
someChannel.send("someEvent");
An alternative is to combine
<h:panelGroup id="foo">
... (some complex UI here) ...
</h:panelGroup>
<o:socket channel="someChannel" scope="view" onmessage="someCommandScript" />
<h:form>
<h:commandScript name="someCommandScript" action="#{bean.pushed}" render=":foo" />
</h:form>
If you pass a |
|||||||||||||||||||||||||||
| sse |
The
Important: All servlet filters mapped on SSE vs WebSocket
Both
When to prefer SSE: for typical unidirectional push use cases (notifications, live updates, dashboards) where HTTP infrastructure compatibility and simplicity are important. SSE is the simpler and more robust choice for most server-to-client push scenarios.
When to prefer WebSocket: when you need dynamic connect/disconnect via the Note: browsers limit concurrent HTTP/1.1 connections to 6 per origin. When the server does not support HTTP/2, multiple SSE channels across multiple tabs may exhaust this limit and queue further HTTP requests (including Ajax requests!). This can be resolved by configuring the server to use HTTP/2, where SSE streams are multiplexed over a single TCP connection. Configuration
No explicit configuration is needed. The SSE endpoint is automatically registered during application startup when at
least one Usage (client)
Declare Here's an example which refers an existing JavaScript listener function (do not include the parentheses!). <o:sse channel="someChannel" onmessage="sseListener" />
function sseListener(message, channel, event) {
console.log(message);
}
Here's an example which declares an inline JavaScript listener function.
<o:sse channel="someChannel" onmessage="function(message) { console.log(message); }" />
The
The SSE connection is automatically established when the page loads and will auto-reconnect when the connection is
lost due to e.g. a network error or server restart. This is a built-in feature of the browser's
In order to successfully reconnect after a server restart, or when switching to a new server node, you need to ensure that session persistence is enabled on the server. Usage (server)
In WAR side, you can inject
@Inject @Push(type=SSE)
private PushContext someChannel;
public void sendMessage(Object message) {
someChannel.send(message);
}
By default the name of the channel is taken from the name of the variable into which injection takes place. The
channel name can be optionally specified via the @Inject @Push(type=SSE, channel="foo") private PushContext bar;
The message object will be encoded as JSON and be delivered as Scopes and users
By default the SSE channel is
The optional <o:sse channel="someChannel" scope="session" ... />
The <o:sse channel="someChannel" scope="view" ... />
The
Additionally, the optional E.g. when you're using container managed authentication or a related framework/library:
<o:sse channel="someChannel" user="#{request.remoteUser}" ... />
Or when you have a custom user entity around in EL as
<o:sse channel="someChannel" user="#{someLoggedInUser.id}" ... />
When the user attribute is specified, then the scope defaults to session and
cannot be set to application. It can be set to view, but this is kind of unusual and should
only be used if the logged-in user represented by user has a shorter lifetime than the HTTP session
(e.g. when your application allows changing a logged-in user during same HTTP session without invaliding it —
which is in turn poor security practice). If in such case a session scoped channel is reused, undefined behavior may
occur when user-targeted push message is sent. It may target previously logged-in user only. This can be solved by
setting the scope to view, but better is to fix the logout to invalidate the HTTP session altogether.
When the
In the server side, the push message can be targeted to the user specified in the
@Inject @Push(type=SSE)
private PushContext someChannel;
public void sendMessage(Object message, User recipientUser) {
Long recipientUserId = recipientUser.getId();
someChannel.send(message, recipientUserId);
}
Multiple users can be targeted by passing a
public void sendMessage(Object message, Group recipientGroup) {
Collection<Long> recipientUserIds = recipientGroup.getUserIds();
someChannel.send(message, recipientUserIds);
}
Channel design hintsYou can declare multiple push channels on different scopes with or without user target throughout the application. Be however aware that the same channel name can easily be reused across multiple views, even if it's view scoped. It's more efficient if you use as few different channel names as possible and tie the channel name to a specific push channel scope/user combination, not to a specific Faces view. In case you intend to have multiple view scoped channels for different purposes, best is to use only one view scoped channel and have a global JavaScript listener which can distinguish its task based on the delivered message. E.g. by sending the message in server as below:
Map<String, Object> message = new HashMap<>();
message.put("functionName", "someFunction");
message.put("functionData", functionData); // Can be Map or Bean.
someChannel.send(message);
Which is processed in the
function someSseListener(message) {
window[message.functionName](message.functionData);
}
function someFunction(data) {
// ...
}
function otherFunction(data) {
// ...
}
// ...
Events (client)
The optional
<o:sse ... onopen="sseOpenListener" />
function sseOpenListener(channel) {
// ...
}
The optional <o:sse ... onerror="sseErrorListener" />
function sseErrorListener(code, channel, event) {
if (code == 500) {
// Connection error. The browser will automatically attempt to reconnect.
}
}
The
The optional <o:sse ... onclose="sseCloseListener" />
function sseCloseListener(code, channel, event) {
if (code == -1) {
// EventSource API not supported by client.
} else if (code == 200) {
// Server explicitly closed the connection (e.g. expired session or view).
} else if (code == 204) {
// Client explicitly closed the connection via OmniFaces.Push.close().
} else if (code == 404) {
// Unknown channel (e.g. randomly guessed or spoofed by endusers or manually reconnected after session expiry).
} else {
// Abnormal close reason (as result of an error).
}
}
The
Events (server)
When an SSE connection has been opened, a new CDI
@ApplicationScoped
public class SseObserver {
public void onOpen(@Observes @Opened SseEvent event) {
String channel = event.getChannel(); // Returns <o:sse channel>.
Long userId = event.getUser(); // Returns <o:sse user>, if any.
// Do your thing with it. E.g. collecting them in a concurrent/synchronized collection.
// Do note that a single person can open multiple SSE connections on same channel/user.
}
public void onSwitch(@Observes @Switched SseEvent event) {
String channel = event.getChannel(); // Returns <o:sse channel>.
Long currentUserId = event.getUser(); // Returns current <o:sse user>, if any.
Long previousUserId = event.getPreviousUser(); // Returns previous <o:sse user>, if any.
// Do your thing with it. E.g. updating in a concurrent/synchronized collection.
}
public void onClose(@Observes @Closed SseEvent event) {
String channel = event.getChannel(); // Returns <o:sse channel>.
Long userId = event.getUser(); // Returns <o:sse user>, if any.
// Do your thing with it. E.g. removing them from collection.
}
}
You could take the opportunity to send another push message to an application scoped channel, e.g. "User X has been logged in" (or out) when a session scoped channel is opened (or closed). Security considerationsIf the SSE channel is declared in a page which is only restricted to logged-in users with a specific role, then you may want to add the URL of the SSE connection to the set of restricted URLs.
The SSE request URL is composed of the URI prefix
<security-constraint>
<web-resource-collection>
<web-resource-name>Restrict access to role USER.</web-resource-name>
<url-pattern>/user/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>USER</role-name>
</auth-constraint>
</security-constraint>
.. and the page
<security-constraint>
<web-resource-collection>
<web-resource-name>Restrict access to role USER.</web-resource-name>
<url-pattern>/user/*</url-pattern>
<url-pattern>/omnifaces.sse/foo</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>USER</role-name>
</auth-constraint>
</security-constraint>
As extra security, particularly for those public channels which can't be restricted by security constraints, the
Business service design hints
In case you'd like to trigger a push from business service side to an application scoped push channel, then you could make use
of CDI events. First create a custom bean class representing the push event something like
public final class PushEvent {
private final String message;
public PushEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
Then use
@Inject
private BeanManager beanManager;
public void onSomeEntityChange(Entity entity) {
beanManager.getEvent().select().fire(new PushEvent(entity.getSomeProperty()));
}
Note that OmniFaces own
Finally just
@Inject @Push(type=SSE)
private PushContext someChannel;
public void onPushEvent(@Observes PushEvent event) {
someChannel.send(event.getMessage());
}
Note that a request scoped bean wouldn't be the same one as from the originating page for the simple reason that
there's no means of a HTTP request anywhere at that moment. For exactly this reason a view and session scoped bean
would not work (as they require respectively the Faces view state and HTTP session which can only be identified by a
HTTP request). A view and session scoped push channel would also not work, so the push channel really needs to be
application scoped. The
In case the trigger in business service side is an asynchronous service method which is in turn initiated in WAR side, then
you could make use of callbacks from WAR side. Let the business service method take a callback instance as argument,
e.g. the
@Asynchronous
public void someAsyncServiceMethod(Entity entity, Consumer<Object> callback) {
// ... (some long process)
callback.accept(entity.getSomeProperty());
}
And invoke the asynchronous service method in WAR as below.
@Inject
private SomeService someService;
@Inject @Push(type=SSE)
private PushContext someChannel;
public void someAction() {
someService.someAsyncServiceMethod(entity, message -> someChannel.send(message));
}
This would be the only way in case you intend to asynchronously send a message to a view or session scoped push
channel, and/or want to pass something from Cluster design hintsIn case your web application is deployed to a server cluster with multiple nodes, and the push event could be triggered in a different node than where the client is connected to, then it won't reach the client. One solution is to activate and configure a JMS topic in the server configuration, trigger the push event via JMS instead of CDI, and use a JMS listener (a message driven bean, MDB) to delegate the push event to CDI. Below is an example extending on the above given business service example.
@ApplicationScoped
public class PushManager {
@Resource(lookup = "java:/jms/topic/push")
private Topic jmsTopic;
@Inject
private JMSContext jmsContext;
public void fireEvent(PushEvent pushEvent) {
try {
Message jmsMessage = jmsContext.createMessage();
jmsMessage.setStringProperty("message", pushEvent.getMessage());
jmsContext.createProducer().send(jmsTopic, jmsMessage);
}
catch (Exception e) {
// Handle.
}
}
}
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/topic/push")
})
public class PushListener implements MessageListener {
@Inject
private BeanManager beanManager;
@Override
public void onMessage(Message jmsMessage) {
try {
String message = jmsMessage.getStringProperty("message");
beanManager.fireEvent(new PushEvent(message));
}
catch (Exception e) {
// Handle.
}
}
}
Then, in your business service, instead of using
@Inject
private BeanManager beanManager;
public void onSomeEntityChange(Entity entity) {
beanManager.fireEvent(new PushEvent(entity.getSomeProperty()));
}
use the newly created
@Inject
private PushManager pushManager;
public void onSomeEntityChange(Entity entity) {
pushManager.fireEvent(new PushEvent(entity.getSomeProperty()));
}
UI update design hints
In case you'd like to perform complex UI updates, then easiest would be to put
<h:panelGroup id="foo">
... (some complex UI here) ...
</h:panelGroup>
<h:form>
<o:sse channel="someChannel" scope="view">
<f:ajax event="someEvent" listener="#{bean.pushed}" render=":foo" />
</o:sse>
</h:form>
Here, the push message simply represents the ajax event name. You can use any custom event name.
someChannel.send("someEvent");
An alternative is to combine
<h:panelGroup id="foo">
... (some complex UI here) ...
</h:panelGroup>
<o:sse channel="someChannel" scope="view" onmessage="someCommandScript" />
<h:form>
<h:commandScript name="someCommandScript" action="#{bean.pushed}" render=":foo" />
</h:form>
If you pass a |
|||||||||||||||||||||||||||
| tagAttribute |
The Consider the following custom tag structure:
<my:tag id="foo">
<my:tag id="bar" />
</my:tag>
Inside the nested tag, the
<my:tag id="foo">
<my:tag />
</my:tag>
then This tag handler is designed to overcome this peculiar problem and unintuitive behavior of nested tagfiles in Mojarra. UsageJust declare the attribute name in top of the tagfile as below. <o:tagAttribute name="id" /> You can optionally provide a default value. <o:tagAttribute name="type" default="text" />Since OmniFaces 2.7/3.2 there is a special case for a <o:tagAttribute name="id"> without
a default value: it will override any autogenerated ID into the form of j_ido[tagId] where [tagId]
is the <o:tagAttribute> tag's own unique ID. |
|||||||||||||||||||||||||||
| toCollectionConverter |
The Usage
This converter is available by converter ID
<h:inputText value="#{bean.commaSeparatedValues}" converter="omnifaces.ToCollectionConverter" />
Since OmniFaces 4.5 it's also available by
<h:inputText value="#{bean.commaSeparatedValues}">
<o:toCollectionConverter />
</h:inputText>
The default delimiter is comma followed by space
The
<h:inputText value="#{bean.uniqueOrderedSemiColonSeparatedNumbers}">
<o:toCollectionConverter delimiter=";"
collectionType="java.util.TreeSet"
itemConverter="jakarta.faces.Integer" />
</h:inputText>
|
|||||||||||||||||||||||||||
| toLowerCaseConverter |
The
This converter does by design no conversion in Usage
This converter is available by converter ID
<h:inputText value="#{bean.email}" converter="omnifaces.ToLowerCaseConverter" />
Since OmniFaces 4.5 it's also available by
<h:inputText value="#{bean.email}">
<o:toLowerCaseConverter />
</h:inputText>
|
|||||||||||||||||||||||||||
| toUpperCaseConverter |
The
This converter does by design no conversion in Usage
This converter is available by converter ID
<h:inputText value="#{bean.zipCode}" converter="omnifaces.ToUpperCaseConverter" />
Since OmniFaces 4.5 it's also available by
<h:inputText value="#{bean.zipCode}">
<o:toUpperCaseConverter />
</h:inputText>
|
|||||||||||||||||||||||||||
| tree |
The
The component value must point to a tree of data objects represented by a
The
Here is a basic usage example where each parent tree node level is treated the same way via a single
<o:tree value="#{bean.treeModel}" var="item" varNode="node">
<o:treeNode>
<ul>
<o:treeNodeItem>
<li>
#{node.index} #{item.someProperty}
<o:treeInsertChildren />
</li>
</o:treeNodeItem>
</ul>
</o:treeNode>
</o:tree>
treeNode
The
The optional treeNodeItem
The
Within treeInsertChildren
The |
|||||||||||||||||||||||||||
| treeInsertChildren |
The This component does not allow any children. |
|||||||||||||||||||||||||||
| treeNode |
The
The |
|||||||||||||||||||||||||||
| treeNodeItem |
The
This component allows a child component of type |
|||||||||||||||||||||||||||
| trimConverter |
The
This converter does by design no conversion in Usage
This converter is available by converter ID
<h:inputText value="#{bean.username}" converter="omnifaces.TrimConverter" />
Since OmniFaces 4.5 it's also available by
<h:inputText value="#{bean.username}">
<o:trimConverter />
</h:inputText>
You can also configure it application wide via below entry in
<converter>
<converter-for-class>java.lang.String</converter-for-class>
<converter-class>org.omnifaces.converter.TrimConverter</converter-class>
</converter>
|
|||||||||||||||||||||||||||
| url |
The
This component fills the gap caused by absence of JSTL Values
You can supply the target URL via either the Domain
When the target URL is specified as
Valid formats and values for
The Request and view parameters
You can add query string parameters to the URL via nested UsageSome examples:
<p>Full URL of current page is: <o:url /></p>
<p>Full URL of another page is: <o:url viewId="/another.xhtml" /></p>
<p>Full URL of current page including view params is: <o:url includeViewParams="true" /></p>
<p>Full URL of current page including query string is: <o:url includeRequestParams="true" /></p>
<p>Domain-relative URL of current page is: <o:url domain="/" /></p>
<p>Scheme-relative URL of current page is: <o:url domain="//" /></p>
<p>Scheme-relative URL of current page on a different domain is: <o:url domain="sub.example.com" /></p>
<p>Full URL of current page on a different domain is: <o:url domain="https://sub.example.com" /></p>
<p>External URL with encoded parameters appended: <o:url value="https://google.com/search">
<o:param name="q" value="#{bean.search}" />
</url></p>
<o:url var="_linkCanonical">
<o:param name="foo" value="#{bean.foo}" />
</o:url>
<link rel="canonical" href="#{_linkCanonical}" />
<o:url var="_linkNext" includeViewParams="true">
<f:param name="page" value="#{bean.pageIndex + 1}" />
</o:url>
<link rel="next" href="#{_linkNext}" />
|
|||||||||||||||||||||||||||
| validateAll |
The The default message is {0}: Please fill out all of those fields
For general usage instructions, refer |
|||||||||||||||||||||||||||
| validateAllOrNone |
The The default message is {0}: Please fill out all or none of those fields
For general usage instructions, refer |
|||||||||||||||||||||||||||
| validateBean |
The
The standard
The standard UsageSome examples Control bean validation per component
<h:commandButton value="submit" action="#{bean.submit}">
<o:validateBean validationGroups="jakarta.validation.groups.Default,com.example.MyGroup" />
</h:commandButton>
<h:selectOneMenu value="#{bean.selectedItem}">
<f:selectItems value="#{bean.availableItems}" />
<o:validateBean disabled="true" />
<f:ajax execute="@form" listener="#{bean.itemChanged}" render="@form" />
</h:selectOneMenu>
Validate a bean at the class level
<h:inputText value="#{bean.product.item}" />
<h:inputText value="#{bean.product.order}" />
<o:validateBean value="#{bean.product}" />
Since OmniFaces 3.8, nested properties are also supported with
<h:inputText value="#{bean.product.item}" />
<h:inputText value="#{bean.product.order}" />
<o:validateBean value="#{bean}" />
Whereby the @Valid private Product product;
When using Class level validation detailsIn order to validate a bean at the class level, all values from input components should first be actually set on that bean and only thereafter should the bean be validated. This however does not play well with the Faces approach where a model is only updated when validation passes. But for class level validation we seemingly can not validate until the model is updated. To break this tie, a copy of the model bean is made first, and then values are stored in this copy and validated there. If validation passes, the original bean is updated. A bean is copied using the following strategies (in the order indicated):
If the above order is not ideal, or if an custom copy strategy is needed (e.g. when it's only needed to copy a few fields for the validation)
a strategy can be supplied explicitly via the
If the copying strategy is not possible due to technical limitations, then you could set
<o:validateBean value="#{bean.product}" method="validateActual" />
This will update the model values and run the validation after update model values phase instead of the validations
phase. The disadvantage is that the invalid values remain in the model and that the action method is anyway invoked.
You would need an additional check for Faces messages
By default, the faces message is added with client ID of the parent
<h:form id="formId">
...
<h:message for="formId" />
<o:validateBean ... />
</h:form>
The faces message can also be shown for all invalidated components using
<h:form>
<h:inputText id="foo" />
<h:message for="foo" />
<h:inputText id="bar" />
<h:message for="bar" />
...
<o:validateBean ... showMessageFor="@all" />
</h:form>
The faces message can also be shown as global message using
<h:form>
...
<o:validateBean ... showMessageFor="@global" />
</h:form>
<h:messages globalOnly="true" />
The faces message can also be shown for specific components referenced by a space separated collection of their
client IDs in
<h:form>
<h:inputText id="foo" />
<h:message for="foo" />
<h:inputText id="bar" />
<h:message for="bar" />
...
<o:validateBean ... showMessageFor="foo bar" />
</h:form>
The faces message can also be shown for components which match
<h:form id="formId">
...
<!-- Unmatched messages shown here: -->
<h:message for="formId" />
...
<h:inputText id="foo" value="#{bean.product.item}" />
<!-- Messages where ConstraintViolation PropertyPath is "item" are shown here: -->
<h:message for="foo" />
...
<o:validateBean ... value="#{bean.product}" showMessageFor="@violating" />
</h:form>
The Message format
The faces message uses a predefined message format, which corresponds to the value of In a form containing properties like First Name, Last Name, Address, Zip Code, and Phone Number where at the bean level, at least one of the name fields must be non-null, overriding the message format can help make a more clear error message.
This can be done by overriding the
jakarta.faces.validator.BeanValidator.MESSAGE = Errors encountered: {0}
However, this change affects all bean validation messages site-wide. In case you'd like to fine-tune the bean
validation message on a per-
<!-- Displays: "First Name, Last Name, Address, Zip Code, Phone Number: First Name and Last Name cannot both be null" -->
<o:validateBean />
<!-- Displays: "Errors encountered: First Name and Last Name cannot both be null" -->
<o:validateBean messageFormat="Errors encountered: {0}" />"
|
|||||||||||||||||||||||||||
| validateEqual |
The The default message is {0}: Please fill out the same value for all of those fields
For general usage instructions, refer |
|||||||||||||||||||||||||||
| validateMultiple |
The
<o:validateMultiple id="myId" components="foo bar baz" validator="#{bean.someMethod}" />
<h:message for="myId" />
<h:inputText id="foo" />
<h:inputText id="bar" />
<h:inputText id="baz" />
whereby the method has the following signature (method name is free to your choice):
public boolean someMethod(FacesContext context, List<UIInput> components, List<Object> values) {
// ...
}
Or, by a managed bean instance which implements the
<o:validateMultiple id="myId" components="foo bar baz" validator="#{validateValuesBean}" />
<h:message for="myId" />
<h:inputText id="foo" />
<h:inputText id="bar" />
<h:inputText id="baz" />
@ManagedBean
@RequestScoped
public class ValidateValuesBean implements MultiFieldValidator {
@Override
public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
// ...
}
}
Design notice
Note that this validator does not throw |
|||||||||||||||||||||||||||
| validateOne |
The The default message is {0}: Please fill out only one of those fields
For general usage instructions, refer |
|||||||||||||||||||||||||||
| validateOneOrMore |
The The default message is {0}: Please fill out at least one of those fields
For general usage instructions, refer |
|||||||||||||||||||||||||||
| validateOneOrNone |
The The default message is {0}: Please fill out only one or none of those fields
For general usage instructions, refer |
|||||||||||||||||||||||||||
| validateOrder |
The
This validator has the additional requirement that the to-be-validated values must implement The default message is {0}: Please fill out the values of all those fields in order
For general usage instructions, refer |
|||||||||||||||||||||||||||
| validateUnique |
The The default message is {0}: Please fill out an unique value for all of those fields
For general usage instructions, refer |
|||||||||||||||||||||||||||
| validateUniqueColumn |
The The default message is {0}: Please fill out an unique value for the entire column. Duplicate found in row {1} UsageUsage example:
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:inputText value="#{item.value}">
<o:validateUniqueColumn />
</h:inputText>
</h:column>
</h:dataTable>
In an invalidating case, only the first row on which the value is actually changed (i.e. the value change event has
been fired on the input component in the particular row) will be marked invalid and a faces message will be added
on the client ID of the input component in the particular row. The default message can be changed by the
<o:validateUniqueColumn message="Duplicate value!" /> |
|||||||||||||||||||||||||||
| validator |
The Usage
When you specify for example the standard
<o:validator validatorId="jakarta.faces.LongRange" minimum="#{item.minimum}" maximum="#{item.maximum}" />
The validator ID of all standard Faces validators can be found in
their javadocs.
First go to the javadoc of the class of interest, then go to
It is also possible to specify the validator message on a per-validator basis using the
<o:validator validatorId="jakarta.faces.LongRange" minimum="#{item.minimum}" maximum="#{item.maximum}"
message="Please enter between #{item.minimum} and #{item.maximum} characters" />
JSF 2.3 compatibility
The |
|||||||||||||||||||||||||||
| viewAction |
The
In below example, the
<f:viewParam name="foo" value="#{bean.foo}" converter="fooConverter" />
<f:viewAction action="otherpage" if="#{bean.foo eq null}" />
This is however not possible with standard
<f:viewParam name="foo" value="#{bean.foo}" converter="fooConverter" />
<o:viewAction action="otherpage" if="#{bean.foo eq null}" />
Only when you set Usage
You can use it the same way as
<o:viewAction action="otherpage" if="#{bean.property eq null}" />
Messaging
You can use the <o:viewAction ... message="Please use a valid link from within the site" /> Note that the message will only be shown when the redirect has actually taken place. The support was added in OmniFaces 3.2. |
|||||||||||||||||||||||||||
| viewParam |
The Stateless mode to avoid unnecessary conversion, validation and model updating on postbacks
The standard
The standard Using name as default for label
The Avoid unnecessary empty parameter in query string
The standard Support bean validation and triggering validate events on null value
The standard Default value when no parameter is set
The Usage
You can use it the same way as
<o:viewParam name="foo" value="#{bean.foo}" />
|
|||||||||||||||||||||||||||
| viewParamValidationFailed |
When the <f:viewParam required="true"> fail
As a precaution; be aware that ExamplesIn the example below the client will be presented an HTTP 400 error when at least one view param is absent.
<f:metadata>
<o:viewParam name="foo" required="true" />
<o:viewParam name="bar" required="true" />
<o:viewParamValidationFailed sendError="400" />
</f:metadata>
In the example below the client will be redirected to "login.xhtml" when the "foo" parameter is absent, regardless of the "bar" parameter. When the "foo" parameter is present, but the "bar" parameter is absent, nothing new will happen. The process will proceed "as usual". I.e. the validation error will end up as a faces message in the current view the usual way.
<f:metadata>
<o:viewParam name="foo" required="true">
<o:viewParamValidationFailed sendRedirect="login.xhtml" />
</o:viewParam>
<o:viewParam name="bar" required="true" />
</f:metadata>
In the example below the client will be presented an HTTP 401 error when the "foo" parameter is absent, regardless of the "bar" or "baz" parameters. When the "foo" parameter is present, but either the "bar" or "baz" parameter is absent, the client will be redirected to "search.xhtml".
<f:metadata>
<o:viewParam name="foo" required="true">
<o:viewParamValidationFailed sendError="401" />
</o:viewParam>
<o:viewParam name="bar" required="true" />
<o:viewParam name="baz" required="true" />
<o:viewParamValidationFailed sendRedirect="search.xhtml" />
</f:metadata>
In a nutshell: when there are multiple Messaging
By default, the first occurring faces message on the parent component will be copied, or when there is none then the
first occurring global faces message will be copied. When
You can override this message by explicitly specifying the <o:viewParamValidationFailed sendRedirect="search.xhtml" message="You need to perform a search." /> ... <o:viewParamValidationFailed sendError="401" message="Authentication failed. You need to login." />
Note, although all of above examples use Design notes
You can technically nest multiple
You can not change the HTTP status code of a redirect. This is not a Faces limitation, but an HTTP
limitation. The status code of a redirect will always end up as the one of the redirected response.
If you intend to "redirect" with a different HTTP status code, then you should be using |
| Type | Function | Description |
|---|---|---|
java.lang.String | abbreviate(java.lang.String, int) | Abbreviate the given text on the given size limit with ellipsis. |
java.lang.Object | addDays(java.lang.Object, int) | Returns a new date instance which is a sum of the given date and the given amount of days. |
java.lang.Object | addHours(java.lang.Object, int) | Returns a new date instance which is a sum of the given date and the given amount of hours. |
java.lang.Object | addMinutes(java.lang.Object, int) | Returns a new date instance which is a sum of the given date and the given amount of minutes. |
java.lang.Object | addMonths(java.lang.Object, int) | Returns a new date instance which is a sum of the given date and the given amount of months. |
java.lang.Object | addSeconds(java.lang.Object, int) | Returns a new date instance which is a sum of the given date and the given amount of seconds. |
java.lang.Object | addWeeks(java.lang.Object, int) | Returns a new date instance which is a sum of the given date and the given amount of weeks. |
java.lang.Object | addYears(java.lang.Object, int) | Returns a new date instance which is a sum of the given date and the given amount of years. |
java.lang.String | capitalize(java.lang.String) | Capitalize the given string, i.e. uppercase the first character. |
java.lang.Object | coalesce(java.lang.Object, java.lang.Object) | Returns the first non-null object from the provided two objects. So, if the first object is not
null, then it will be returned, otherwise the second object will be returned. |
java.lang.String | concat(java.lang.Object, java.lang.Object) | Concatenate the string representation of the given objects. This is useful when you don't know beforehand if one
of the both hands is a string or is null, otherwise the EL
#{bean.string1.concat(bean.string2)} can just be used. |
boolean | contains(java.lang.Object[], java.lang.Object) | Returns true if the string representation of an item of the given array equals to the string
representation of the given item. This returns false if either the array or the item is null. This
is useful if you want to for example check if #{paramValues.foo} contains a certain value. |
java.lang.String | convert(java.lang.String, java.lang.Object) | Convert given object to string using Converter#getAsString(FacesContext, UIComponent, Object) of the
converter identified by the given converter ID, invoked with FacesContext#getCurrentInstance(),
UIComponent#getCurrentComponent(FacesContext) and given object as arguments. |
java.lang.Object[] | createArray(int) | Creates and returns a dummy object array of the given size. This is useful if you want to iterate n times
over an <ui:repeat>, which doesn't support EL in begin and end
attributes. |
java.lang.Integer[] | createIntegerArray(int, int) | Creates and returns an integer array which starts at the given integer and ends at the given integer, inclusive.
This is useful if you want to for example populate a <f:selectItems> which shows an integer
range to represent days and years. If the begin is greater than end, then the array will be decremental. If the
begin equals end, then the array will contain only one item. |
int | daysBetween(java.lang.Object, java.lang.Object) | Returns the amount of days between two given dates. This will be negative when the end date is before the start date. |
java.lang.String | encodeBase64(java.lang.String) | Base64-encode the given string. This is useful for cases where you need to create data URLs. |
java.lang.String | encodeURI(java.lang.String) | URI-encode the given string using UTF-8. This is useful for cases where you need to embed path parameters in URLs. |
java.lang.String | encodeURL(java.lang.String) | URL-encode the given string using UTF-8. This is useful for cases where you can't use
<f:param>. |
java.lang.String | escapeJS(java.lang.String) | Escapes the given string according the JavaScript code rules. This escapes among others the special characters, the whitespace, the quotes and the unicode characters. Useful whenever you want to use a Java string variable as a JavaScript string variable. |
java.lang.Object | evalAttribute(jakarta.faces.component.UIComponent, java.lang.String) | Evaluates an attribute of a component by first checking if there's a value expression associated with it, and only if there isn't one
look at a component property with that name.
The regular attribute collection ( |
java.lang.String | flagEmoji(java.lang.String) | Converts the given ISO 3166-1 alpha-2 country code to corresponding Unicode flag emoji. |
java.lang.String | format1(java.lang.String, java.lang.Object) | Format the given string with 1 parameter using MessageFormat API. The locale is obtained by
Faces#getLocale(). Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
because EL functions do not support varargs methods nor overloaded function names. |
java.lang.String | format2(java.lang.String, java.lang.Object, java.lang.Object) | Format the given string with 2 parameters using MessageFormat API. The locale is obtained by
Faces#getLocale(). Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
because EL functions do not support varargs methods nor overloaded function names. |
java.lang.String | format3(java.lang.String, java.lang.Object, java.lang.Object, java.lang.Object) | Format the given string with 3 parameters using MessageFormat API. The locale is obtained by
Faces#getLocale(). Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
because EL functions do not support varargs methods nor overloaded function names. |
java.lang.String | format4(java.lang.String, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object) | Format the given string with 4 parameters using MessageFormat API. The locale is obtained by
Faces#getLocale(). Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
because EL functions do not support varargs methods nor overloaded function names. |
java.lang.String | format5(java.lang.String, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object) | Format the given string with 5 parameters using MessageFormat API. The locale is obtained by
Faces#getLocale(). Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
because EL functions do not support varargs methods nor overloaded function names. |
java.lang.String | formatBytes(java.lang.Long) | Format the given bytes to nearest 10n in the default pattern of the default locale with IEC binary
unit (KiB, MiB, etc) with rounding precision of 1 fraction. For example (with English locale):
Faces#getLocale(). |
java.lang.String | formatBytesForLocale(java.lang.Long, java.lang.Object) | Format the given bytes to nearest 10n in the default pattern of the given locale with IEC binary
unit (KiB, MiB, etc) with rounding precision of 1 fraction. For example (with English locale):
Locale object or a string representation. |
java.lang.String | formatCurrency(java.lang.Number, java.lang.String) | Format the given number as currency with the given symbol in the default pattern of the default locale. This is
useful when you want to format numbers as currency in for example the title attribute of an UI
component, or the itemLabel attribute of select item, or wherever you can't use the
<f:convertNumber> tag. The format locale will be set to the one as obtained by
Faces#getLocale(). |
java.lang.String | formatCurrencyForLocale(java.lang.Number, java.lang.String, java.lang.Object) | Format the given number as currency with the given symbol in the default pattern of the given locale. This is
useful when you want to format numbers as currency in for example the title attribute of an UI
component, or the itemLabel attribute of select item, or wherever you can't use the
<f:convertNumber> tag. The given locale can be a Locale object or a string
representation. |
java.lang.String | formatDate(java.lang.Object, java.lang.String) | Format the given date in the given pattern with the default timezone. This is useful when you want to format
dates in for example the title attribute of an UI component, or the itemLabel attribute
of select item, or wherever you can't use the <f:convertDateTime> tag. The format locale will
be set to the one as obtained by Faces#getLocale(). |
java.lang.String | formatDateWithTimezone(java.lang.Object, java.lang.String, java.lang.Object) | Format the given date in the given pattern with the given timezone. This is useful when you want to format dates
in for example the title attribute of an UI component, or the itemLabel attribute of
select item, or wherever you can't use the <f:convertDateTime> tag. The format locale will be
set to the one as obtained by Faces#getLocale(). |
java.lang.String | formatNumber(java.lang.Number, java.lang.String) | Format the given number in the given pattern. This is useful when you want to format numbers in for example the
title attribute of an UI component, or the itemLabel attribute of select item, or
wherever you can't use the <f:convertNumber> tag. The format locale will be set to the one as
obtained by Faces#getLocale(). |
java.lang.String | formatNumberDefault(java.lang.Number) | Format the given number in the default pattern of the default locale. This is useful when you want to format
numbers in for example the title attribute of an UI component, or the itemLabel
attribute of select item, or wherever you can't use the <f:convertNumber> tag. The default
locale is the one as obtained by Faces#getLocale(). |
java.lang.String | formatNumberDefaultForLocale(java.lang.Number, java.lang.Object) | Format the given number in the default pattern of the given locale. This is useful when you want to format
numbers in for example the title attribute of an UI component, or the itemLabel
attribute of select item, or wherever you can't use the <f:convertNumber> tag. The given
locale can be a Locale object or a string representation. |
java.lang.String | formatPercent(java.lang.Number) | Format the given number as percentage in the default pattern of the default locale. This is useful when you want
to format numbers as percentage in for example the title attribute of an UI component, or the
itemLabel attribute of select item, or wherever you can't use the
<f:convertNumber> tag. The default locale is the one as obtained by Faces#getLocale(). |
java.lang.String | formatPercentForLocale(java.lang.Number, java.lang.Object) | Format the given number as percentage in the default pattern of the given locale. This is useful when you want
to format numbers as percentage in for example the title attribute of an UI component, or the
itemLabel attribute of select item, or wherever you can't use the
<f:convertNumber> tag. The given locale can be a Locale object or a string
representation. |
java.lang.String | formatThousands(java.lang.Number) | Format the given number to nearest 10n (rounded to thousands) in the default pattern of the default
locale, immediately suffixed (without space) with metric unit (k, M, G, T, P or E), rounding half up with a
precision of 3 digits, whereafter trailing zeroes in fraction part are stripped.
For example (with English locale):
Faces#getLocale().
If the value is null, NaN or infinity, then this will return null. |
java.lang.String | formatThousandsForLocale(java.lang.Number, java.lang.Object) | Format the given number to nearest 10n (rounded to thousands) in the default pattern of the given
locale, immediately suffixed (without space) with metric unit (k, M, G, T, P or E), rounding half up with a
precision of 3 digits, whereafter trailing zeroes in fraction part are stripped.
For example (with English locale):
Locale object or a string representation.
If the value is null, NaN or infinity, then this will return null. |
java.lang.String | formatThousandsUnit(java.lang.Number, java.lang.String) | Format the given number to nearest 10n (rounded to thousands) in the default pattern of the default
locale, suffixed with a space, the metric unit prefix (k, M, G, T, P or E) and the given unit, rounding half up
with a precision of 3 digits, whereafter trailing zeroes in fraction part are stripped.
For example (with English locale and unit B):
Faces#getLocale().
If the value is null, NaN or infinity, then this will return null. |
java.lang.String | formatThousandsUnitForLocale(java.lang.Number, java.lang.String, java.lang.Object) | Format the given number to nearest 10n (rounded to thousands) in the default pattern of the given
locale, suffixed with a space, the metric unit prefix (k, M, G, T, P or E) and the given unit, rounding half up
with a precision of 3 digits, whereafter trailing zeroes in fraction part are stripped.
For example (with English locale and unit B):
Locale object or a string representation.
If the value is null, NaN or infinity, then this will return null. |
java.lang.String | getDayOfWeek(java.lang.Integer) | Returns the day of week name from the mapping associated with the given day of week number in ISO 8601 order
(Monday first) for the current locale. For example: "1=Monday", "2=Tuesday", etc. The locale is obtained by
Faces#getLocale(). |
java.util.Map | getDaysOfWeek() | Returns a mapping of day of week names in ISO 8601 order (Monday first) for the current locale. For example:
"Monday=1", "Tuesday=2", etc. This is useful if you want to for example populate a <f:selectItems>
which shows all days of week. The locale is obtained by Faces#getLocale(). The mapping is per locale
stored in a local cache to improve retrieving performance. |
java.lang.String | getMonth(java.lang.Integer) | Returns the month name from the mapping associated with the given month number for the current locale. For
example: "1=January", "2=February", etc. The locale is obtained by Faces#getLocale(). |
java.util.Map | getMonths() | Returns a mapping of month names by month numbers for the current locale. For example: "January=1", "February=2",
etc. This is useful if you want to for example populate a <f:selectItems> which shows all
months. The locale is obtained by Faces#getLocale(). The mapping is per locale stored in a local cache
to improve retrieving performance. |
java.lang.String | getRemoteAddr() | Returns the Internet Protocol (IP) address of the client that sent the request. This will first check the
X-Forwarded-For request header and if it's present, then return its first IP address, else just
return HttpServletRequest#getRemoteAddr() unmodified.
This is also available in EL as |
java.lang.String | getRequestBaseURL() | Returns the HTTP request base URL. This is the URL from the scheme, domain until with context path, including
the trailing slash. This is the value you could use in HTML <base> tag.
This is also available in EL as |
java.lang.String | getRequestDomainURL() | Returns the HTTP request domain URL. This is the URL with the scheme and domain, without any trailing slash.
This is also available in EL as |
java.lang.String | getRequestURLWithQueryString() | Returns the HTTP request URL with query string. This is the full request URL with query string as the enduser
sees in browser address bar.
This is also available in EL as |
java.lang.String | getShortDayOfWeek(java.lang.Integer) | Returns the short day of week name from the mapping associated with the given day of week number in ISO 8601
order (Monday first) for the current locale. For example: "1=Mon", "2=Tue", etc. The locale is obtained by
Faces#getLocale(). |
java.util.Map | getShortDaysOfWeek() | Returns a mapping of short day of week names in ISO 8601 order (Monday first) for the current locale. For example:
"Mon=1", "Tue=2", etc. This is useful if you want to for example populate a <f:selectItems>
which shows all short days of week. The locale is obtained by Faces#getLocale(). The mapping is per locale
stored in a local cache to improve retrieving performance. |
java.lang.String | getShortMonth(java.lang.Integer) | Returns the short month name from the mapping associated with the given month number for the current locale. For
example: "1=Jan", "2=Feb", etc. The locale is obtained by Faces#getLocale(). |
java.util.Map | getShortMonths() | Returns a mapping of short month names by month numbers for the current locale. For example: "Jan=1", "Feb=2",
etc. This is useful if you want to for example populate a <f:selectItems> which shows all
short months. The locale is obtained by Faces#getLocale(). The mapping is per locale stored in a local
cache to improve retrieving performance. |
java.lang.String | graphicImageURL(java.lang.String) |
Returns Usage example:
<a href="#{o:graphicImageURL('images.full(product.imageId)')}">
<o:graphicImage value="#{images.thumb(product.imageId)}" />
</a>
|
java.lang.String | graphicImageURLWithType(java.lang.String, java.lang.String) |
Returns Usage example:
<a href="#{o:graphicImageURLWithType('images.full(product.imageId)', 'png')}">
<o:graphicImage value="#{images.thumb(product.imageId)}" type="png" />
</a>
|
java.lang.String | graphicImageURLWithTypeAndLastModified(java.lang.String, java.lang.String, java.lang.Object) |
Returns Usage example:
<a href="#{o:graphicImageURLWithTypeAndLastModified('images.full(product.imageId)', 'png', product.lastModified)}">
<o:graphicImage value="#{images.thumb(product.imageId)}" type="png" lastModified="#{product.lastModified}" />
</a>
|
long | hoursBetween(java.lang.Object, java.lang.Object) | Returns the amount of hours between two given dates. This will be negative when the end date is before the start date. |
boolean | isInstance(java.lang.String, java.lang.Object) | Returns true if given object is an instance of the class as identified by given class name. |
java.util.List | iterableToList(java.lang.Iterable) | Converts a Iterable<E> to a List<E>.
When iterating specifically over a Set using the above mentioned components |
jakarta.faces.model.DataModel | iterableToModel(java.lang.Iterable) | Converts an Iterable<E> to a DataModel<E>.
When iterating specifically over a Set using the above mentioned components
For those same components |
java.lang.String | joinArray(java.lang.Object, java.lang.String) | Joins all elements of the given array to a single string, separated by the given separator. |
java.lang.String | joinCollection(java.util.Collection, java.lang.String) | Joins all elements of the given collection to a single string, separated by the given separator. |
java.lang.String | joinMap(java.util.Map, java.lang.String, java.lang.String) | Joins all elements of the given map to a single string, separated by the given key-value pair separator and entry separator. |
java.util.List | mapToList(java.util.Map) | Converts a Map<K, V> to a List<Map.Entry<K, V>>. Each of the entries has the
usual getKey() and getValue() methods. |
boolean | matches(java.lang.String, java.lang.String) | Returns true if the given string matches the given pattern. |
long | minutesBetween(java.lang.Object, java.lang.Object) | Returns the amount of minutes between two given dates. This will be negative when the end date is before the start date. |
int | monthsBetween(java.lang.Object, java.lang.Object) | Returns the amount of months between two given dates. This will be negative when the end date is before the start date. |
java.lang.String | parenthesize(java.lang.Object) | Parenthesize the given object. This will only wrap the given object in parenthesis when it's not empty or zero. |
java.lang.String | prettyURL(java.lang.String) | URL-prettify the given string. It performs the following tasks:
|
java.lang.String | printStackTrace(java.lang.Throwable) | Print the stack trace of the given exception. |
java.lang.String | replaceAll(java.lang.String, java.lang.String, java.lang.String) | Replace all matches of the given pattern on the given string with the given replacement. |
java.lang.Object[] | reverseArray(java.lang.Object[]) | Returns a copy of the array with items in reversed order. |
long | secondsBetween(java.lang.Object, java.lang.Object) | Returns the amount of seconds between two given dates. This will be negative when the end date is before the start date. |
java.util.List | setToList(java.util.Set) | Converts a Set<E> to a List<E>. |
java.lang.Object[][] | splitArray(java.lang.Object, int) | Splits the given array into an array of subarrays of the given fragment size. This is useful for creating nested
<ui:repeat> structures, for example, when positioning a list of items into a grid based
layout system such as Twitter Bootstrap. |
java.util.List | splitList(java.util.List, int) | Splits the given list into a list of sublists of the given fragment size. This is useful for creating nested
<ui:repeat> structures, for example, when positioning a list of items into a grid based
layout system such as Twitter Bootstrap. |
java.lang.String | stripTags(java.lang.String) | Remove XML tags from a string and return only plain text. |
java.lang.String | toJson(java.lang.Object) | Encode given object as JSON.
Currently, this delegates directly to Json#encode(Object). |
int | weeksBetween(java.lang.Object, java.lang.Object) | Returns the amount of weeks between two given dates. This will be negative when the end date is before the start date. |
int | yearsBetween(java.lang.Object, java.lang.Object) | Returns the amount of years between two given dates. This will be negative when the end date is before the start date. |
Output generated by Vdldoc View Declaration Language Documentation Generator.