Introduction to Java Server Faces (JSF)

JSF is the basic frontend framework (but it runs on the backend side) for web applications developed in Java/Jakarta EE. It allows a smooth integration of java EE code with web pages. In this session, we will experience how JSF works in some simple examples. Please follow these steps on your configuration to 1) make sure it works for your 2) get familiar with the basics of using JSF and Jakarta EE. We will use JSF in most of the remaining projects.

1. In Intellij IDEA, create new Project: give it a name, select project template Web Application, type package name in group: edit field;, on NEXT select Jakarta EE 9, and select specifications "Context and Dependency Injection (CDI)", and "Server Faces (JSF)", and implementations "Mojarra Server Faces", and "Weld SE".

2. Delete the automatically generated index.jsp (we do not want to use JSP), and the HelloServlet class (we are not going to use simple plain Servlet any more) - just press DEL key on both items.

3. Right-click webapp under src/main, and select New - JSF / Facelets - JSF File, give it a name, such as index. This will create JSF file called index.xhtml. JSF framework uses XHTML format, which can contain pieces of code in "expression language". It is an XML file that contains special tags assigned to several XML namespaces (i.e. tags that start with <h:i, or <fn, etc., for example <h:outputLabel> that produces a label). When this XHTML file is requested by a client browser, it is translated/parsed by server-side JSF engine to produce the resulting HTML that is sent to the browser.

4. You can now try to run this application to see that it is working, and shows the hello world message. Usually, when you run it - a browser opens or an option to select from the installed browsers appears. If not, just open the URL localhost:8080/YOUR_APP_URL/index.xhtml - where YOUR_APP_URL can be found in the "Edit configurations" - below the Glassfish dropdown box on the upper right in the IDE.

5. Let's modify this example to create a simple calculator app - that will show the result of A+B (entered in an html form), and also sum all the sums calculated during the user session and the whole runtime(deployment) of the application. Let's create a Java class that will be a Java Bean (i.e. plain Java class with some attributes and getters/setters), for instance:
package ee.fir;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;

// these annotations make this class into request-scoped CDI bean - that's an object that can be accessed from the XHTML file
// it's scope can be request - as here, or session, or application - as in the two other classes below
// we do not construct objects of this class, for each request it will be automatically instantiated, and it will have
// the same name (for accessing it from XHTML file) as is the name of the class, but first letter lower case. it is also possible
// to use a different name, if you give the annotation a parameter
@RequestScoped
@Named
public class First {
    // this annotation automatically inserts a reference to another CDI-bean (in this case session-scoped) 
    @Inject
    SessionSum sessionSum;
    // same for another application-scoped CDI-bean (CDI stands for context-dependency injection - and that is 
    // a mechanism that allows to do exactly this kind of automatic initialization)
    @Inject
    AppBean applicationSum;

    public First() {
        message = "Hello JSF!";
    }
    private String message;
    private int a, b, sum = 0;
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    public int getA() { return a; }
    public void setA(int a) { this.a = a; }
    public int getB() { return b; }
    public void setB(int b) { this.b = b; }
    public int getSum() {
        sessionSum.add(a + b);
        applicationSum.add(a + b);
        return a + b;
    }
    public void setSum(int sum) { this.sum = sum; }
    public int getSessionSum() { return sessionSum.getSessionSum(); }
    public int getApplicationSum() { return applicationSum.getApplicationSum(); }
}
6. Now replace the <h:outputLabel> with <h:outputLabel value="${first.message}" /> and the original message will be replaced with the one which is assigned in the above constructor. But in order to make the code compile and run, we first need to create two more Java classes - the two other CDI beans:
package ee.fir;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
import java.io.Serializable;

@SessionScoped
@Named
public class SessionSum implements Serializable {
    int sessionSum = 0;
    public void add(int num) {
        sessionSum += num;
    }
    public int getSessionSum() {
        return sessionSum;
    }
}
	
package ee.fir;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Named;

@ApplicationScoped
@Named
public class AppBean {
    int applicationSum = 0;
    public void add(int num) {
        applicationSum += num;
    }
    public int getApplicationSum()
    {
        return applicationSum;
    }
}
	
7. Finally, we add the form to enter the A, and B numbers to be summed and tags to display the output:
<?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">
<f:view>
    <h:outputLabel value="${first.message}" />
    <br /> <br />
    <h:graphicImage library="img" name="img.jpg" />
    <br /> <br />
    <h:form>
        <h:inputText id="A" label="Enter A:" value="#{first.a}" required="true"> </h:inputText>
        <br />
        <h:inputText id="B" label="Enter B:" value="#{first.b}" required="true"> </h:inputText>
        <br />
        <h:commandButton action="index" value="Add"> </h:commandButton>
        <br/>
        Sum: <h:outputText value="#{first.sum}" escape="false"> </h:outputText>
        <br />
        Session sum: <h:outputText value="#{first.sessionSum}" escape="false"> </h:outputText>
        <br />
        Application sum: <h:outputText value="#{first.applicationSum}" escape="false"> </h:outputText>
    </h:form>
</f:view>
</html>
	
Notice the following: The resulting application looks like this in the browser:


The resulting application as complete Intellij project can be downloaded here: jsf-first.zip.

FInally, take a look at the list of the possible JSF tags that be used in the XHTML file: