First time here? Get an overview of all topics you'll find answers for on this blog here.

Tired of text/plain ? Have a look at my online courses or YouTube channel for more Java, Spring Framework & Jakarta EE content.

.Scrolling through my news feed on Twitter I get flooded with new releases of npm modules and more and more blog articles about server-side rendering technologies for the latest Single Page Application frameworks like Angular, React. What about proven and productive technologies likes JavaServer Faces? The following tweet summarized my current feelings:

As I personally really like React and used it in the past for several projects, I am not that happy about the bunch of additional npm packages. To be up-to-date you have stick to the latest versions and this is sometimes awful. If you are also developing the backend you have to observe more frameworks and libraries. For most of the (enterprise) applications, it's all about validating user inputs, manipulating, storing, and displaying data. This can be easily achieved with a SPA and a backend like Spring or Java EE. Nevertheless, you need experience in both technologies, and staying up-to-date is more complex.

My way to JavaServer Faces

To get a whole overview of the server-side vs. client-side web development and to overcome my (maybe) Junior mentality of using every new shiny framework I wanted to know more about server-side rendering with Java. I always had the prejudice that it's quite old, slow, and not usable. But I never took the time to try it for my own.

At one of the airhacks.com Adam Bien (@AdamBien) did a quick intro to JavaServer Faces (JSF). He showed us how easy it was to get started and create JSF components in seconds. To get deeper insights into this mature technology I bought the book The Definitive Guide to JSF in Java EE 8. Both authors Bauke Scholtz (@OmniFaces) & Arjan Tijms (@arjan_tijms) did an awesome job with this book. They cover all aspects of web development with JSF: WebSockets, Validation, Internationalization, Security, etc. and I can highly recommend this awesome book.

Today I'll show you a quick Hello World with JSF 2.3 and Maven on Payara 5.182 to make you familiar with the technology. Like every Java EE part (CDI, JPA, EJB …) JSF has a formal specification and several reference implementations. The most popular implementations for JSF are Apache MyFaces and Mojarra.

JavaServer Faces project setup

To start your web development your pom.xml needs at least the following dependency:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>de.rieckpil.blog</groupId> <artifactId>hello-world-jsf-23</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <failOnMissingWebXml>false</failOnMissingWebXml> </properties> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <finalName>hello-world-jsf</finalName> </build> </project> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <? xml version = "1.0" encoding = "UTF-8" ?> <project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns : xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi : schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion> 4.0.0 </modelVersion> <groupId> de.rieckpil.blog </groupId> <artifactId> hello-world-jsf-23 </artifactId> <version> 1.0-SNAPSHOT </version> <packaging> war </packaging> <properties> <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding> <project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding> <maven.compiler.source> 1.8 </maven.compiler.source> <maven.compiler.target> 1.8 </maven.compiler.target> <failOnMissingWebXml> false </failOnMissingWebXml> </properties> <dependencies> <dependency> <groupId> javax </groupId> <artifactId> javaee-api </artifactId> <version> 8.0 </version> <scope> provided </scope> </dependency> </dependencies> <build> <finalName> hello-world-jsf </finalName> </build> </project>

The dependency javax:javaee-api brings you the formal specification with several classes and annotations. The implementation of several Java EE APIs is provided by the application server (e.g. Payara, OpenLiberty, Wildfly etc.). Marking the dependency as provided will lead to a thin war deployment where the Java EE dependency is not packaged to the war file as it is part of the application server. The war file will just contain your business logic and JSF views.

To configure your web application and later on JSF you need a web.xml file which has to be placed in /src/main/webapp/WEB-INF :

<?xml version="1.0" encoding="UTF-8"?> <web-app version="4.0" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.xhtml</welcome-file> </welcome-file-list> </web-app> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <? xml version = "1.0" encoding = "UTF-8" ?> <web-app version = "4.0" xmlns = "http://xmlns.jcp.org/xml/ns/javaee" xmlns : xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi : schemaLocation = "http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" > <servlet> <servlet-name> Faces Servlet </servlet-name> <servlet-class> javax.faces.webapp.FacesServlet </servlet-class> <load-on-startup> 1 </load-on-startup> </servlet> <servlet-mapping> <servlet-name> Faces Servlet </servlet-name> <url-pattern> *.xhtml </url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file> index.xhtml </welcome-file> </welcome-file-list> </web-app>

With this configuration, you enable the central FacesServlet, define the mapping of JSF related views and the welcome file. JSF follows the MVC approach and your views are mostly written as .xhtml files (a detailed JSF MVC explanation can be found here).

Writing your first JSF view

A simple Hello World view ( index.xhtml ) with an input field and a button to display the Hello World message can look like the following and should be stored at /src/main/webapp :

<!DOCTYPE html> <html lang="en" 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"> <h:head> <title>Hello World JSF 2.3</title> </h:head> <h:body> <h:form> <h:outputLabel for="input" value="Who do you want to greet?"/> <h:inputText id="input" value="#{helloWorldBacking.name}"/> <h:commandButton value="Submit" action="#{helloWorldBacking.greetPerson}"> </h:commandButton> <br/> <h:outputText value="#{helloWorldBacking.greet}"/> </h:form> </h:body> </html> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <!DOCTYPE html> <html lang = "en" 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" > <h:head> <title> Hello World JSF 2.3 </title> </h:head> <h:body> <h:form> <h:outputLabel for = "input" value = "Who do you want to greet?" /> <h:inputText id = "input" value = "#{helloWorldBacking.name}" /> <h:commandButton value = "Submit" action = "#{helloWorldBacking.greetPerson}" > </h:commandButton> <br/> <h:outputText value = "#{helloWorldBacking.greet}" /> </h:form> </h:body> </html>

You may notice the prefix <h:…> on several HTML elements which is one of the main differences to normal HTML (.html) files. With this prefix, you reference a specific namespace and in the case of <h:…> it's the namespace of the basic HTML elements. There are several other namespaces you can use like <f:…>. They all provide a bunch of predefined components and functionality. In the example above we are using a form with a label for an input field, a submit button, and a placeholder.

Another difference to normal HTML elements is the use of the following syntax #{xyz.value}. You can find it for the label value and the action for the submit button. This is an expression language where you can reference fields and methods of so-called backing beans. In our example, I am referencing two fields (name and greet) and a method (greetPerson) of the backing bean helloWorldBacking . The values get replaced when the JSF view is rendered on the server.

Providing data with a JSF backing bean

The name of the backing bean is the name of the Java class which is annotated with @Named and a CDI scope like @RequestScoped if nothing else is configured. The backing bean looks like the following:

package de.rieckpil.blog; import javax.enterprise.context.RequestScoped; import javax.inject.Named; @Named @RequestScoped public class HelloWorldBacking { private String name; private String greet; public void greetPerson() { this.greet = "Hello World: " + this.name + " !"; } public String getGreet() { return greet; } public void setGreet(String greet) { this.greet = greet; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package de . rieckpil . blog ; import javax . enterprise . context . RequestScoped ; import javax . inject . Named ; @Named @RequestScoped public class HelloWorldBacking { private String name ; private String greet ; public void greetPerson ( ) { this . greet = "Hello World: " + this . name + " !" ; } public String getGreet ( ) { return greet ; } public void setGreet ( String greet ) { this . greet = greet ; } public String getName ( ) { return name ; } public void setName ( String name ) { this . name = name ; } }

With this setup, you don't have to create any JavaScript code. Inserting a name to the input field and pressing submit will render the same page with the Hello world message. This is just a small example of a quick JSF intro. There is a lot more to discover like WebSockets, AJAX calls, UI layout, notifications, etc.

For a quick deployment on your local machine I created a simple Dockerfile for starting the app:

FROM payara/server-full COPY target/hello-world-jsf.war $DEPLOY_DIR 1 2 FROM payara/server-full COPY target/hello-world-jsf.war $DEPLOY_DIR

You can find the Hello World example with the required steps to run this application locally on GitHub.

I'll definitely play more with JSF and start using the awesome component library PrimeFaces which brings a lot of ready-to-use components (e.g. date picker, dialogs, data tables, panels, menu bars etc.) and keep you up-to-date. If you want to get further information about JSF, have a look at the following book The Definitive Guide to JSF in Java EE 8. For further code examples use this overview or my other JSF blog posts.

Have fun using JavaServer Faces,

Phil.