-
The <o:notification> is a UIComponent which integrates the browser Web Notifications API with SSE (Server-Sent Events) based push. It opens a one-way (server to client) SSE connection and shows incoming push messages as browser notifications.
Prerequisites
This component requires the PWAResourceHandler to be activated by adding the following line to the <h:head> because it provides the service worker mandatory for cross-platform notification support via ServiceWorkerRegistration.showNotification():
<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 @Push(type=NOTIFICATION) qualified injection point using the channel name matching the channel attribute of this component, so that the SseEndpoint will be auto-activated.
Basic Usage
Declare the <o:notification> tag in the Faces view with a channel name.
<o:notification channel="notifications" />
In the server side, inject the push context and send notification messages created via createNotificationMessage(String, String).
@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 user attribute can be set to the unique identifier of the logged-in user, so that notifications can be targeted to a specific user.
<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 stacked attribute to true:
<o:notification channel="notifications" stacked="true" />
The requireInteraction attribute controls whether the notification remains visible until the user explicitly interacts with it (click or dismiss), rather than auto-closing after a timeout. This is useful for important alerts that should not be missed:
<o:notification channel="alerts" requireInteraction="true" />
The silent attribute suppresses the device's notification sound and vibration:
<o:notification channel="updates" silent="true" />
Event Handlers
The <o:notification> supports click and close event handlers.
<o:notification channel="notifications" onclick="handleClick" onclose="handleClose" />
The event's detail object contains data and tag. The data object contains the channel name and the optional url. The tag is set to the component's client ID (when not stacked) and is used by the browser for notification deduplication: a new notification with the same tag replaces the previous one instead of stacking.
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 <h:commandScript> to bridge the client-side event to the server. For example, to mark a notification as read when the user clicks it:
<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 OmniFaces.Notification.getPermission(), which returns "granted", "denied", "default", or "unsupported".
const notificationPermission = OmniFaces.Notification.getPermission();
You can use OmniFaces.Notification.show to programmatically show notifications using JavaScript. The first argument is the channel name, the second the title, the optional third the body, and the optional fourth a URL:
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 icon attribute is passed to the Notifications API, but custom notification icons are not guaranteed to work across all platforms. As of March 2026, macOS and Linux with GNOME always display the browser's own application icon instead, due to OS/desktop-environment-level policies. Custom icons do work on Windows and Android. Use PNG format at 192x192 or larger for best results.
<o:notification channel="alerts" icon="#{resource['icons/alert.png']}" />
VDL documentation
API documentation
Java source code
org.omnifaces.cdi.push.SseEndpointorg.omnifaces.cdi.Pushorg.omnifaces.cdi.PushContextorg.omnifaces.cdi.push.Notificationorg.omnifaces.resourcehandler.PWAResourceHandlerorg.omnifaces.cdi.push.Sse