webfaces is a library that helps you build JavaServer Faces components using Web Components.
JavaServer Faces (JSF) is the standard API for building Java web applications (part of the Java Enterprise Edition, or Java EE) specification. A key part of JSF applications is a sever-side user interface component model. JSF pages ("views") are built out of smaller UI components. For examples, see the PrimeFaces showcase.
Web Components are a set of relatively new HTML5 standards that bring a native component model to HTML, with a full-fledged JavaScript API. Since the standard is integrated into browsers, it allows you to build reusable components that work like ordinary HTML tags. Web Components aren’t tied to a specific JavaScript framework. For examples, see webcomponents.org.
JSF components often expose both a server-side Java API and a client-side JavaScript API. Usually the client-side APIs are built with proprietary frameworks and libraries such as a jQuery. However, Web Components are particularly well suited for for exposing the client-side API. Such components provide a more consistent, standard approach for client-side integration and are more likely to work with third-party JavaScript web frameworks.
For more information about how these two component models compare, see the presentation JavaServer Faces and HTML5 Web Components: Synergy? (presented at JavaOne and Devnexus).
This is a very simple Maven project; once you have Maven installed, simply run mvn install
from the project root folder. The output JAR file will be in the target
folder
Once you have built the project, just copy the JAR file into the WEB-INF/lib folder of your JSF web app. This will give you access to a few special components which allow you to write a JSF composite component that renders as a web component:
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:jsf="http://xmlns.jcp.org/jsf"
xmlns:wf="uri:webfaces">
<cc:interface name="HelloWorld">
<cc:attribute name="message" type="java.lang.String"/>
</cc:interface>
<cc:implementation>
<wf:template id="hello-world-template" pass-through-attribute="blah">
<style>
:host {
display: block;
border-style: solid;
border: 1px;
}
</style>
<div>
Hello world, <span id="message">#{cc.attrs.message}</span>.
</div>
<div>
You are using #{facesContext.externalContext.request.getHeader('User-Agent')}.
</div>
</wf:template>
<hello-world class="test" id="#{cc.attrs.id}" message="#{cc.attrs.message}!"/>
<wf:renderOnce group="webfaces-demo-hello-world">
<h:outputScript id="hello-world-script">
class HelloWorld extends HTMLElement {
static get observedAttributes() {
return ['message'];
}
constructor() {
super();
let template = document.querySelector('#hello-world-template').content.cloneNode(true);
let root = this.attachShadow({mode: 'open'});
root.appendChild(template);
}
get message() {
return this.hasAttribute('message');
}
set message(message) {
if (message) {
this.setAttribute('message', message);
} else {
this.removeAttribute('message');
}
}
/** Fires when an instance was inserted into the document */
connectedCallback() {
};
/** Fires when an instance was removed from the document */
disconnectedCallback() {
};
/** Fires when an attribute was added, removed, or updated */
attributeChangedCallback(attr, oldVal, newVal) {
if (attr === 'message') {
let messageElement = this.shadowRoot.querySelector('#message');
messageElement.innerText = newVal;
}
}
/** Fires when the element is moved to a new document */
adoptedCallback() {
}
}
window.customElements.define('hello-world', HelloWorld);
</h:outputScript>
</wf:renderOnce>
</cc:implementation>
</ui:composition>
You can then use this in any JSF page like any other JSF component:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:demo="http://java.sun.com/jsf/composite/webfaces-demo">
<f:view transient="true"/>
<h:head>
<script type="text/javascript" src="#{facesContext.externalContext.requestContextPath}/resources/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
</h:head>
<h:body>
<demo:hello-world id="hello1" message="#{param.message}"/>
<input id="messageInput" value="#{param.message}" onkeyup="updateComponents(this.value)"></input>
<script type="text/javascript">
function updateComponents(value) {
document.querySelector('#hello1').message = value;
}
</script>
</h:body>
</html>
The key here is the client-side API. Since hello-world is a web component, you can retreive it via the DOM like any other element, and it will have whichever additional properties and methods you have defined. This avoids the extra effort required to build custom scaffolding for client-side widgets; you can simply #UseThePlatform.
There are two separate sample applications available which make use of this library. Take a look at these apps to see how to use the webfaces to build JSF components with Web Components APIs:
This software has been released under the MIT License:
Copyright 2016-2017 Virtua, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Brought to you by virtua.tech