/ JSF

JavaServer Faces overview for beginners

4youngpadawans.com presents JavaServer Faces overview for beginners featuring JSF


One of the first web oriented frameworks I got interested in was JavaServer Faces known as JSF. This article gives summary of JSF framework and tools necessary to create and run JSF web applications.

JSF is JavaEE component based framework for creating web applications and, among other things, it is supporting template pages, AJAX calls and server-side state saving. Its XHTML pages are transformed at server side in pure HTML and then served to browser. Pages are backed up by server side classes called managed beans, created in Java programming language utilizing all existing libraries from Java ecosystem.

JSF concept and (dis)advantages

Modern mainstream concepts of building web applications suggest that client-side (front-end, UI) and server-side (e.g. web service) should be strictly separated.
For example, if you decide to build front-end with React or Angular you are forced to use completely different framework/project on server-side to provide web service functionalities.
That concept usually requires at least 2 specialized developers: one for front-end and one for back-end.

On the other side, in JSF client and server side are tightly coupled allowing single developer to create UI and handle server functionalities.

That concept helped me a lot in my rookie days when I started to learn web programming

  • to learn how web actually works,
  • to understand what parts are necessary to create fully operative web application
  • to handle my pet projects quickly and alone without need to include some other developer (at least during project early stages).

JSF example

JSF web page

JSF page can be created using

  • JSF UI components where every component is rendered as standard HTML element.
  • inline JavaScript using <script> tag
  • JavaScript files using h:outputScript component
  • inline CSS using <style> tag
  • CSS class files using h:outputStylesheet tag
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">

    <f:view contentType="text/html">
        <h:head>
            <f:facet name="first">
                <meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
                <title>Login page</title>
            </f:facet>
            <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
            <style>
                h3   {color: #989898;}
            </style>
        </h:head>

        <h:body>
            <f:facet name="last" >
                <h:outputStylesheet library="css" name="styles.css"/>
            </f:facet>

            <h3>Login</h3>

            <h:form id="form" prependId="true">
                <h:messages id="messages" showDetail="true"/>
                <h:panelGrid columns="2">
                    <h:outputText value="Username" styleClass="redLabel"/>
                    <h:inputText id="username" value="#{loginController.username}" onkeyup="onKeyUp(event);"/>

                    <h:outputText value="Password" style="color: blue;"/>
                    <h:inputText id="password" value="#{loginController.password}"/>

                    <h:commandButton value="Login"  actionListener="#{loginController.onLogin()}" >
                        <f:ajax execute=":form" render=":form:messages" resetValues="true"/>
                    </h:commandButton>
                    <h:panelGroup>
                        <h:selectBooleanCheckbox value="#{loginController.rememberMe}"/>
                        <h:outputText value="Remember me"/>
                    </h:panelGroup>
                </h:panelGrid>
            </h:form>

            <script>
                //JQuery
                $(document).ready(function () {
                    console.log("Page is ready");
                    $("#form\\:password").change(function (eventObject) {
                        console.log("Password changed");
                        var target = event.target || event.srcElement;
                        console.log("Password=" + target.value);
                    });
                });

                //vanilla JS
                function onKeyUp(event) {
                    console.log("Key code=" + event.keyCode);
                    var target = event.target || event.srcElement;
                    console.log("User name=" + target.value);
                }
            </script>
        </h:body>
    </f:view>
</html>

Notice that

  • JSF component's value property is mapped to corresponding property of managed bean using following syntax: value={beanName.propertyName}
  • after form is submitted, all input values become available in managed bean for further processing,
  • it is possible to do partial process/submit by utilizing execute property of f:ajax component. For example, following submits only username value:
<f:ajax execute=":form:username"/>
  • it is possible to do partial page update by utilizing render property of f:ajax component. For example, after AJAX call is finished, following updates only messages component:
<f:ajax render=":form:messages"/>

JSF managed bean

Managed bean is server side class holding

  • properties (e.g. String, Integer, List,...),
  • methods/functions
    that can be reffered from and called by JSF web page.
package beans;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

@ManagedBean(name = "loginController")
@ViewScoped
public class LoginController implements Serializable {
    
    //properties
    private String username;
    private String password;
    private Boolean rememberMe;
    
    //class constructor (not required)
    public LoginController() {
        //executed on class instance creation
    }

    @PostConstruct
    public void init() {
        //executed after class instance is created
        //do some initialization here
        username = "";
        password = "";
        rememberMe = false;
    }

    //getter and setter methods for properties
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    
    public Boolean getRememberMe() {
        return rememberMe;
    }
    public void setRememberMe(Boolean rememberMe) {
        this.rememberMe = rememberMe;
    }

    //server side method called (via Ajax in this example) when login button is clicked
    public void onLogin() {
        System.out.println("Username=" + username + ", Password=" + password + ", Remember me=" + String.valueOf(rememberMe));
        if (username.isEmpty() || password.isEmpty()) {
            showMessage(FacesMessage.SEVERITY_WARN, "Warning", "Username and password are required");
        } else {
            showMessage(FacesMessage.SEVERITY_INFO, "Info", "You are logged in" + (rememberMe ? " and remembered" : ""));
        }
    }
    
    public void showMessage(FacesMessage.Severity severity, String summary, String  detail){
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, summary, detail);
        FacesContext.getCurrentInstance().addMessage("loginMessage", facesMsg);
    }
}

Annotation @ManagedBean turns standard Java class into class managed by JSF with methods that can be called from JSF pages.
Scope annotations define life span of managed bean. For example

  • @RequestScoped bean lives only during one request-response sequence,
  • @ViewScoped bean is created in the moment when page is shown in browser and destroyed after page is closed in browser. It is capable to preserve state.
  • @SessionScoped bean lives during entire user session period and it is also capable to preserve state. For each user session one instance of session scoped bean is created.
  • @ApplicationScoped is alive from the moment when application is started until its destroyed (stopped).

jsf_example_login_page

Primefaces JSF components

Back in 2011 I discovered Primefaces, component library for JSF. Even in that early days that open source project (I think in version 2.x) was packed with features.

When I saw their showcase for the fist time my jaw dropped and my eyes started glittering in darkness of my cave. I realized that I discovered the golden pot and that

With PrimeFaces, even without digging deep into native JavaScript, CSS and HTML, I can easily create functionalities that I saw only on some public web pages always wondering how they were created and what magician did it in the first place

Later I understood how PrimeFaces actually does the magic:

  • its built on top of JSF 2.x framework inheriting all native functionalities,
  • it enhances JSF native functionalities by
    • integrating JavaScript (JQuery library) into components to provide fancy UI features and asynchronous AJAX calls to server-side,
    • using to inbuilt, pre-made CSS libraries (themes) to provide UI look and feel.

StackOverflow Q&A

Similar like all other self-thought developers, when I encounter on some problem I usually ask for the help of our best friend Google. In case of JSF, StackOverflow web site is packed with answers on almost every basic as well as more advanced common questions.
I need to admit that almost everything I know about JSF, I learned it there.

BalusC is legendary StackOverflow member specialized in JSF and JavaEE. His answers are more then answers: they are opened book packed with useful info. He is also creator of OmniFaces library which extends and simplifies JSF native functionalities.

IDE - Integrated Development Environment

It is very important to choose and work in IDE that makes you makes you comfortable and relaxed using it. Luckily, there are 3 major IDEs that that can be used for creating JSF apps. All of them are built in Java and provide both Windows and Linux versions.

NetBeans IDE

In the beginning I mostly used NetBeans IDE to create, modify, run and debug my JSF projects.
It had (still has :) ) wide community support, hundreds of online tutorials, inbuilt syntax pre-checking, intelliSense with code auto-completion, project templates, integration with application servers, etc.. In short, everything that I needed to create JSF app was there.

IntelliJ Idea IDE

From the moment when Google decided to use IntelliJ Idea as base for their Android Studio I've decided to try out Idea IDE for my JSF projects... I am using it since then.
There are 3 reasons why I switched to Idea:

  • NetBeans was taken over by Oracle (along with Java) and I had feeling that NetBeans became neglected and its progress somehow stopped
    • tutorials were becoming more and more outdated,
    • major disadvantages (e.g. loading slowness) of NetBeans were not taken care of and never improved
  • beside JSF, I was working on Android projects and switching between different IDE's in one day was giving me hard time to adopt,
  • and finally, my personal opinion is that IntelliJ's IDEA is simply better and adopting much faster to new trends and technologies.

Recently I've heard that NetBeans moved to Apache foundation. That are good news promising that my first Java IDE will be taken care much better in the future.

Eclipse IDE

While NetBeans and IntelliJ Idea are (mainly) used for creating Java apps, Eclipse IDE is multilingual environment. Beside JavaEE package, it has variety of other packages specialized for certain area.
I've used it mostly for C/C++ development and my close colleague is using it for JavaEE/JSF.

There is also package specialized for front-end developers working with JavaScript/HTML/CSS. Maybe its worth trying it and compare it with popular front-end Visual Studio Code IDE. It is free anyways :)

So if you want one-for-all IDE, Eclipse is the right choice.

Application server

Application server is actually

  • providing environment implementing JavaEE specification,
  • running our JSF applications making it accessible to browser.

GlassFish

Since I was using NetBeans IDE, naturally I had started with Glashfish app server which is reference JavaEE implementation. Also it was part of NetBeans installation package providing quick start in setting up basic programming environment.

Over the time 2 facts started to bother me

  • GlassFish was too slow,
  • parts of my JSF apps didnt work out-of-box on other application servers

Reasons for both pros can be explained with fact that GlassFish is, after all, just a reference implementation and that it contains many libraries and services that are even not required by JSF framework.

Apache Tomcat

With aim to improve performance of my JSF apps, and despite the fact that GlassFish had detailed and easy-to-use admin console,

  • I switched to Apache Tomcat noticing significant improvement of server boot and page loading speed,
  • more and more I started to use Spring framework realizing that my JSF apps will be more easier ported and ran on other application servers since Spring has its own implementations of common JavaEE methods.

The other fact that made me drop GlassFish is that in 2013 Oracle announced that they are dropping commercial support for GlassFish and my oppinion is that, since then, GlashFish was neglected (similar like NetBeans) and that even known bugs were not fixed (or fixed too late for me).

Payara is fork of GlassFish providing commercial support. They introduced much more light-weight and embeddable Payara Micro version.

Conclusion

Although JSF is little bit defying modern front-back-end concepts, my opinion is that it is worth trying and I would recommend it to every beginner or more experienced developer currently using other technologies.

JSF is mature and stable technology utilizing Java at its best, it has good IDE and app server support and it would definitely be good addition to your existing portfolio.

Recently JavaEE was moved under Eclipse Foundation and renamed to Jakarta EE. Hopefully those guys will be able to improve platform for the benefit of our future JSF applications.

JavaServer Faces overview for beginners
Share this