Getting Started
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against Jakarta Faces 4.1 (API jakarta.faces-api 4.1.2, part of Jakarta EE 11), Eclipse Mojarra 4.1.17
and Apache MyFaces Core 4.1.4, Java 17 or later (Java 21 for GlassFish 8), WildFly 41.0.1.Final, GlassFish 8.0.5, Apache
Tomcat 11.0.26 and Weld weld-servlet-shaded 6.0.4.Final. The versions were checked on 2026-10-08. Faces 4.0 (Jakarta
EE 10, Java 11 or later) behaves the same for everything on this page except where the text says otherwise; Faces 5.0
(Jakarta EE 12) is still a milestone (jakarta.faces-api 5.0.0-M9) and is mentioned only as upcoming.
The Tomcat and Weld part of the page was run for real: the exact WAR below was built with Maven and served by Apache
Tomcat 11.0.26 (embedded) with Weld 6.0.4.Final, once with Mojarra 4.1.17 and once with MyFaces 4.1.4, and the
initial request, an invalid postback and a valid postback were driven with curl. The lifecycle trace in the walk below
is the output of that run. The WildFly and GlassFish commands are taken from their official guides and were not run on
this page.
The goal is the smallest application that shows every moving part of Faces: a view, a backing bean, a form that posts back, a validation message and a navigation-free round trip. The rest of this section grows the same application, the Bookshelf (a catalogue of books, authors and reviews), one concept at a time; here it only has a text box that adds a book title to a shelf.
What You Build
A single page, index.xhtml, shows a text field and an Add button. The field is required. When it is empty the page is
shown again with a message; when it has a title the page is shown again with a confirmation. Behind the page there is
one Java class, ShelfBean.
GET and POST /bookshelf/index.xhtml"] servlet["FacesServlet
runs the lifecycle"] view["index.xhtml
Facelets view with h:form,
h:inputText, h:commandButton"] bean["ShelfBean
@Named @RequestScoped"] browser --> servlet servlet --> view view -->|"EL: title property,
addBook action"| bean servlet -->|"HTML plus view state"| browser
The Project
The application is an ordinary Maven WAR. The tree below is everything it needs; the full production layout of the Bookshelf (templates, resources, contracts) is shown on the project setup page of this section.
bookshelf/
pom.xml
src/main/java/org/example/bookshelf/web/ShelfBean.java
src/main/java/org/example/bookshelf/web/PhaseTracer.java (optional, used in the lifecycle walk)
src/main/webapp/index.xhtml
src/main/webapp/WEB-INF/beans.xml
src/main/webapp/WEB-INF/faces-config.xml
src/main/webapp/WEB-INF/web.xml
The pom.xml below builds one WAR that targets either kind of server through Maven profiles. By default the Jakarta
EE API is provided, because WildFly and GlassFish already contain Faces, CDI and everything else; the WAR is then
tiny. The tomcat and myfaces profiles add what a plain servlet container lacks: a Faces implementation and a CDI
container, as the Mojarra and MyFaces documentation require.
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>bookshelf</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<!-- Faces, CDI, Servlet, EL ... all provided by a Jakarta EE 11 server -->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>11.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>bookshelf</finalName>
</build>
<profiles>
<!-- mvn clean package -Ptomcat : Tomcat 11 with Mojarra and Weld -->
<profile>
<id>tomcat</id>
<dependencies>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.faces</artifactId>
<version>4.1.17</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-shaded</artifactId>
<version>6.0.4.Final</version>
</dependency>
</dependencies>
</profile>
<!-- mvn clean package -Pmyfaces : Tomcat 11 with MyFaces and Weld -->
<profile>
<id>myfaces</id>
<dependencies>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>4.1.4</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-impl</artifactId>
<version>4.1.4</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-shaded</artifactId>
<version>6.0.4.Final</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>
Source: Mojarra 4.1 README (requirements and Maven coordinates) and Apache MyFaces Core 4.1 (requirements and dependencies)
Three small descriptors complete the WAR. beans.xml switches CDI on for the archive, faces-config.xml declares the
Faces 4.1 schema and registers the optional lifecycle listener used below, and web.xml sets two context parameters
and a welcome file.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_1.xsd"
version="4.1" bean-discovery-mode="annotated"/>
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_4_1.xsd"
version="4.1">
<lifecycle>
<phase-listener>org.example.bookshelf.web.PhaseTracer</phase-listener>
</lifecycle>
</faces-config>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_1.xsd"
version="6.1">
<context-param>
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>jakarta.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>1</param-value>
</context-param>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
A few points about these files deserve a sentence each.
-
There is no
FacesServletdeclaration inweb.xml. Both implementations register the servlet themselves when they find a Faces application (observed in the test runs), and Mojarra’s README states that without an explicit mapping the servlet is reachable on*.xhtml,*.jsf,*.facesand/faces/*. The running application above relied on exactly that. Declaring the mapping yourself (the project setup page does) is optional but removes the extra mappings. -
jakarta.faces.PROJECT_STAGEdefaults toProductionwhen it is not set. In that stage the Facelets compiler does not look for changed pages.Developmentturns on extra diagnostics, and the explicitjakarta.faces.FACELETS_REFRESH_PERIOD(seconds between checks,-1for never) makes edited XHTML visible after a page reload. Set it explicitly rather than relying on the stage: with only the stage set, an edited page was not picked up within a few seconds in the Mojarra 4.1.17 test run, while1picked it up on the next reload. Remove both parameters, or set the stage toProduction, before deploying for real. -
The namespace and schema versions (
web-app_6_1,beans_4_1,web-facesconfig_4_1) are the Jakarta EE 11 ones. A Faces 4.0 application usesweb-app_6_0,beans_4_0andweb-facesconfig_4_0withversion="4.0". -
bean-discovery-mode="annotated"means that only classes with a bean-defining annotation (@RequestScoped,@ApplicationScoped, …) become beans. That is what the bean below carries.
The Backing Bean
A backing bean is a plain Java class that the view reads and writes through Expression Language. In current Faces it is
a CDI bean: @Named gives it an EL name and a scope annotation from jakarta.enterprise.context gives it a lifetime.
@RequestScoped means one instance per HTTP request, which is the right default for a form that does not need to
remember anything between requests.
package org.example.bookshelf.web;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;
@Named
@RequestScoped
public class ShelfBean {
private String title;
private String message;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMessage() {
return message;
}
/** Action method: runs only when the submitted data is valid. */
public void addBook() {
message = "Added \"" + title + "\" to the shelf.";
}
}
The default EL name of a @Named bean is the simple class name with the first letter in lower case, so ShelfBean is
shelfBean. The getters and setters are what EL uses: #{shelfBean.title} calls getTitle() when the page is
rendered and setTitle(...) when a value is submitted. Note that the getters only return fields. Anything slow or
with side effects belongs in an action method such as addBook, because a getter can be called several times in one
request.
Where the books are outdated: the books written for JSF 1.x and 2.x declare this class with @ManagedBean (or a
<managed-bean> element in faces-config.xml) and a javax.faces.bean scope. Those annotations were deprecated in
Faces 2.3 and removed in Faces 4.0, together with the javax namespace itself, so the same class must be written with
CDI as above. The Jakarta EE Tutorial’s configuration chapter still contains passages about configuring managed beans
that describe what Faces 4.0 removed; do not follow them.
The View
A Faces view is written in Facelets, the view declaration language, as an XHTML page. The tags come from the standard
HTML component library, bound to the URN jakarta.faces.html.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="jakarta.faces.html">
<h:head>
<title>Bookshelf</title>
</h:head>
<h:body>
<h1>Bookshelf</h1>
<h:form id="shelfForm">
<h:messages id="msgs"/>
<h:outputLabel for="title" value="Title: "/>
<h:inputText id="title" value="#{shelfBean.title}" required="true"
requiredMessage="Please type a title."/>
<h:commandButton id="add" value="Add" action="#{shelfBean.addBook}"/>
<p><h:outputText value="#{shelfBean.message}" rendered="#{not empty shelfBean.message}"/></p>
</h:form>
</h:body>
</html>
Source: Jakarta EE Tutorial: Using the Facelets Tag Libraries and HTML Components and h:inputText (VDL 4.1)
Each tag has a job.
| Tag | What it does |
|---|---|
|
Render |
|
Renders an HTML |
|
Renders a text input. |
|
Renders a submit button. |
|
Renders every message queued during the request (validation, conversion or application messages), as a list. It is
how the user sees why a submission was rejected. |
|
A label tied to an input by its |
The #{...} syntax is deferred Expression Language: Faces evaluates it later, as part of the lifecycle, and it can both
read and write. That is the key difference from a one-shot ${...} expression of a JSP-style page.
Source: h:form, h:messages, h:commandButton and h:outputText (VDL 4.1)
What changed across versions for this page: the jakarta.faces.html URN replaced http://xmlns.jcp.org/jsf/html (which
itself replaced http://java.sun.com/jsf/html) in Faces 4.0. The old namespaces still worked in the Mojarra 4.1.17 test
run, but their removal is planned for Faces 5.0, so new pages should use the URNs. JSP views, which the first books
use, were removed in Faces 4.0; a view is always Facelets XHTML now.
Run It on WildFly or GlassFish
A Jakarta EE server already contains a Faces implementation and a CDI container, so the default build is enough: no
profile, and the Jakarta EE API stays provided.
mvn clean package
# result: target/bookshelf.war
WildFly 41. The Getting Started guide asks for Java SE 17 or later. Download the distribution from
https://wildfly.org/downloads/ and unzip it; $JBOSS_HOME below is the unzipped directory. Start the standalone
server, then deploy by copying the archive: the deployment scanner notices it. The application is served at
http://localhost:8080/bookshelf/, because by default the context root is the WAR file name without its extension.
$JBOSS_HOME/bin/standalone.sh # terminal 1: leave it running
cp target/bookshelf.war $JBOSS_HOME/standalone/deployments/ # terminal 2
The command-line interface does the same and is better for repeated redeployments. After ./jboss-cli.sh --connect
(which connects to localhost:9990), deploy takes the path of the archive and --force replaces an existing deployment
of the same name; undeploy bookshelf.war removes it.
$JBOSS_HOME/bin/jboss-cli.sh --connect
deploy target/bookshelf.war --force
GlassFish 8. The Installation Guide states that Eclipse GlassFish 8 requires Java 21 or higher, and the Quick Start
Guide describes it as the Jakarta EE 11 platform. Download and unzip it from https://glassfish.org/download.html (it
unpacks to a glassfish8 directory, as-install below), start the default domain and deploy with asadmin. The HTTP
port is 8080 and the Administration Console is on port 4848. --force=true redeploys an application that already
exists, and undeploy takes the application name, not the file name.
as-install/bin/asadmin start-domain
as-install/bin/asadmin deploy target/bookshelf.war
# redeploy after a rebuild
as-install/bin/asadmin deploy --force=true target/bookshelf.war
# remove it
as-install/bin/asadmin undeploy bookshelf
Open http://localhost:8080/bookshelf/ in the browser. Both servers log deployment problems to their server log, which is
the first place to look if the page does not appear.
Run It on Tomcat 11 with Weld
Tomcat is a servlet container, not a Jakarta EE server. It has the Servlet 6.1 and Expression Language 6.0 APIs but no
Faces and no CDI, so the WAR carries both. Mojarra’s README lists the Maven coordinates for servlet containers
(org.glassfish:jakarta.faces 4.1.x and org.jboss.weld.servlet:weld-servlet-shaded 6.0.x) and MyFaces lists Java 17,
Servlet 6.1, EL 6.0 and CDI 4.1 as its requirements; the tomcat and myfaces profiles above are exactly that. Tomcat
11.0.x supports Java 17 and later.
mvn clean package -Ptomcat # Mojarra 4.1.17 + Weld 6.0.4.Final
# or
mvn clean package -Pmyfaces # MyFaces 4.1.4 + Weld 6.0.4.Final
The two profiles produce the same page. Only the jars in WEB-INF/lib differ: for the first one
jakarta.faces-4.1.17.jar, weld-servlet-shaded-6.0.4.Final.jar and jakarta.annotation-api-3.0.0.jar; for the second
myfaces-api-4.1.4.jar, myfaces-impl-4.1.4.jar, the Weld jar and the annotation jar. Use one implementation per WAR,
never both.
To run it, download Tomcat 11 from https://tomcat.apache.org/download-11.cgi, unzip it, copy the WAR into webapps and
start the server. With the default configuration a running Tomcat deploys a WAR dropped into webapps and redeploys it
when a newer file replaces it. The application is then at http://localhost:8080/bookshelf/.
cp target/bookshelf.war "$CATALINA_HOME/webapps/"
"$CATALINA_HOME/bin/catalina.sh" run # foreground, logs in the terminal
The wiring that people expect to write by hand turned out to be unnecessary, and it helps to know why.
-
No listener in
web.xml. The Weld reference guide says the listenerorg.jboss.weld.environment.servlet.Listenerneeds registering inweb.xmlonly for a container withoutServletContainerInitializersupport, or to control listener ordering. In the test run Weld started by itself ("Initialize Weld using ServletContainerInitializer" in the log), and Faces, found inWEB-INF/lib, installed itself the same way (Mojarra’sConfigureListener, or MyFaces'MyFacesContainerInitializer). -
No
META-INF/context.xmlfor this page. Weld’s guide describes acontext.xmlresource namedBeanManager(factoryorg.jboss.weld.resources.ManagerObjectFactory) plus a matchingresource-env-refinweb.xml. That binds the CDIBeanManagerto JNDI so that other code can look it up atjava:comp/env/BeanManager. Faces beans did not need it in the test run; add it only when something in the WAR looks the manager up through JNDI. -
beans.xmlis required. WithoutWEB-INF/beans.xmlthe test run found noshelfBean, even though the class has@RequestScoped: Weld in a servlet container did not discover the bean without it. This is the likeliest cause of the first-run error in the last section. -
Harmless start-up lines. Weld logs that it falls back to Java reflection for annotated bean discovery (add
io.smallrye:jandexto speed start-up up) and that transactional services are not available. Neither is a problem for a Faces application.
The Weld reference guide states that Tomcat 10.1 is the supported version, because that is the one it is tested with.
The test run on Tomcat 11.0.26 with Weld 6.0.4.Final worked, and Mojarra’s README names weld-servlet-shaded 6.0.x for
servlet containers. Weld 7.0.0.Final also exists, but it is the CDI 5 line for Jakarta EE 12; stay on 6.0.x with Faces
4.1. The Tomcat and Weld page of this section covers the full Tomcat setup (JNDI, JSTL, validation, production hardening).
Mojarra or MyFaces
Both implementations implement the same specification, so the page and the bean did not change between the two runs. The differences visible at this level are small, and worth knowing because they surface in error messages and in browser developer tools.
| Observation | Mojarra 4.1.17 | MyFaces 4.1.4 |
|---|---|---|
Extra hidden field in the form |
none besides the view state |
|
HTML output |
indented as in the Facelets source |
compact, whitespace between tags removed |
Development stage banner |
none seen |
a console warning that MyFaces is in development mode and an empty message container at the end of the body |
Server log in Development |
an INFO line announcing Mojarra 4.1.17 for the context |
an INFO line "MyFaces Core has started" with the elapsed time |
Those are rendering details, not contracts: never write code or tests that depend on them. The configuration
parameters differ too: MyFaces documents its own org.apache.myfaces.* parameters beside the standard
jakarta.faces.* ones in its configuration table, and Mojarra uses com.sun.faces.* ones. A parameter with one
of those prefixes does nothing on the other implementation. Stay with the jakarta.faces.* parameters unless you
have chosen an implementation.
The Edit, Deploy and Reload Loop
Development goes fastest when you know which edits need a redeployment and which only need a browser refresh.
template or resource"| save["Save the file
in src/main/webapp"] kind -->|"Java class,
web.xml, faces-config.xml,
beans.xml, pom.xml"| build["mvn clean package"] save --> sync["Copy to the deployed WAR
or let the IDE or server
sync the exploded WAR"] build --> deploy["Redeploy the WAR
asadmin deploy --force=true,
jboss-cli deploy --force,
or replace the file in webapps"] sync --> reload["Reload the page in the browser"] deploy --> reload reload --> look{"Looks right?"} look -->|"No: read the
server log"| edit look -->|"Yes"| done(["Next change"]) done --> edit
-
XHTML only. The Facelets compiler re-reads a page when its refresh period has elapsed, so a saved edit shows after the next reload. This works against an exploded (unzipped) deployment, which every server and IDE can produce from the project; for a zipped WAR you must redeploy, because the file the server reads is inside the archive.
-
Anything compiled or configured. Java classes,
faces-config.xmlandbeans.xmlare read when the application starts, so those edits need a redeploy. With the default server-side state saving, Faces keeps the saved view of each page in the user’s session, so the page that was open before the redeployment is stale and its next postback fails with aViewExpiredException; reload the page first. Both are normal and not a sign that anything is broken. -
Hot-swapping Java. A debugger session can replace method bodies without a redeploy, and servers offer hot-reload features, but a changed field, annotation or class set still needs a redeploy. The project setup page and the testing page of this section go deeper.
A Walk Through the Lifecycle
Faces processes every request through a lifecycle of six phases, run by the FacesServlet: Restore View, Apply Request
Values, Process Validations, Update Model Values, Invoke Application and Render Response. The request processing
lifecycle page of this section explains them all. This is what each does for the page above.
To see it, the optional PhaseTracer class prints a line before and after every phase. It implements
jakarta.faces.event.PhaseListener, listens to PhaseId.ANY_PHASE, and is registered by the <lifecycle> element of
faces-config.xml shown earlier.
package org.example.bookshelf.web;
import java.util.logging.Logger;
import jakarta.faces.event.PhaseEvent;
import jakarta.faces.event.PhaseId;
import jakarta.faces.event.PhaseListener;
public class PhaseTracer implements PhaseListener {
private static final Logger LOG = Logger.getLogger(PhaseTracer.class.getName());
@Override
public void beforePhase(PhaseEvent event) {
LOG.info("before " + event.getPhaseId());
}
@Override
public void afterPhase(PhaseEvent event) {
LOG.info("after " + event.getPhaseId());
}
@Override
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}
Source: PhaseListener (API 4.1)
The initial request
The user types the address, so the browser sends a GET. The log of the test run shows two phases:
before RESTORE_VIEW 1
after RESTORE_VIEW 1
before RENDER_RESPONSE 6
after RENDER_RESPONSE 6
-
Restore View. There is no view state in the request, so Faces creates an empty view for
/index.xhtmland, because nothing was submitted, goes straight to Render Response. -
Render Response. Facelets reads
index.xhtmland builds the component tree: a form, a messages component, an input, a button and an output. EL expressions are evaluated to produce the output (#{shelfBean.title}callsgetTitle(), which returnsnull, shown as an empty field). Each component then writes its HTML. The form also writes a hiddenjakarta.faces.ViewStatefield, and the server saves the tree so that it can be restored when the form comes back.
Source: Jakarta Faces 4.1 specification: Standard Request Processing Lifecycle Phases (the log is the output of the Tomcat 11 test run described above)
A postback that fails validation
The user clicks Add with an empty field. The browser sends a POST to the same URL carrying the form fields and the
view state: this is a postback.
before RESTORE_VIEW 1
after RESTORE_VIEW 1
before APPLY_REQUEST_VALUES 2
after APPLY_REQUEST_VALUES 2
before PROCESS_VALIDATIONS 3
after PROCESS_VALIDATIONS 3
before RENDER_RESPONSE 6
after RENDER_RESPONSE 6
-
Restore View. The view state in the request identifies the tree saved earlier, and Faces restores it.
-
Apply Request Values. Each component reads its own value from the request parameters; the input stores the empty string as its submitted value. Nothing has touched the bean yet.
-
Process Validations. The input is
required, and an empty submitted value is invalid, so Faces queues aFacesMessagewith the text ofrequiredMessageand skips ahead to Render Response after this phase. -
Skipped phases. Update Model Values and Invoke Application do not run once validation failed:
setTitleandaddBookwere never called, and the bean is not changed. Faces jumps directly to Render Response. -
Render Response. The same tree is written again.
h:messagesnow has a message and shows it; the input keeps what the user typed. The response is200 OKwith the page, not an error.
Source: Jakarta Faces 4.1 specification: Standard Request Processing Lifecycle Phases (the log is the output of the Tomcat 11 test run described above)
A successful postback
With a title, for example Dune, the lifecycle runs all six phases:
before RESTORE_VIEW 1
after RESTORE_VIEW 1
before APPLY_REQUEST_VALUES 2
after APPLY_REQUEST_VALUES 2
before PROCESS_VALIDATIONS 3
after PROCESS_VALIDATIONS 3
before UPDATE_MODEL_VALUES 4
after UPDATE_MODEL_VALUES 4
before INVOKE_APPLICATION 5
after INVOKE_APPLICATION 5
before RENDER_RESPONSE 6
after RENDER_RESPONSE 6
-
Process Validations. The value
Dunepasses therequiredcheck. -
Update Model Values. Only now is the bean written: Faces calls
setTitle("Dune")on a new request-scopedShelfBeaninstance. -
Invoke Application. The command button was the one clicked, so its action runs:
addBook()builds the message. -
Render Response. Because
addBookreturns nothing (void), there is no navigation outcome and the same view is shown again. The bean instance of this very request still holds the message, soh:outputTextrendersAdded "Dune" to the shelf.. The next request starts with a fresh bean and an empty message, which is why a page that must show a confirmation after a redirect needs the flash scope; the flash and post-redirect-get page of this section covers it.
| Phase | Initial GET | POST, title empty | POST, title typed |
|---|---|---|---|
1 Restore View |
creates an empty view, goes to phase 6 |
restores the saved tree |
restores the saved tree |
2 Apply Request Values |
skipped |
input keeps the submitted text |
input keeps the submitted text |
3 Process Validations |
skipped |
|
passes |
4 Update Model Values |
skipped |
skipped |
|
5 Invoke Application |
skipped |
skipped |
|
6 Render Response |
builds the tree, writes HTML and view state |
same tree with the message |
same tree with the confirmation |
If you know ASP.NET Web Forms, this is the same idea as its postback and page lifecycle, with the difference that Faces separates conversion and validation from the model update and never calls the action when the data is invalid; the Web Forms page lifecycle and postback page compares them.
Common First-Run Errors
The errors below are the ones met most often with a first Faces application. The first three were reproduced with the application of this page.
| Symptom | Cause | Fix |
|---|---|---|
|
EL found no bean of that name. On Tomcat the test run showed it when |
Check the EL name (class name with a lower-case first letter), keep |
The WAR fails to start on Tomcat with |
Mojarra 4.1 needs CDI 4.1 and the WAR has no CDI container. |
Add |
|
The posted form carries the view state of a tree the server no longer has: the application restarted, the session expired, or the server dropped it to save memory. |
Reload the page before submitting again. Tune the session timeout for real applications, and use the exception handling page of this section to show a friendly page. |
Clicking Add shows the same page and seems to do nothing |
A validation or conversion error queued a message but the page has no |
Add |
The literal text |
The request did not go through the |
Request the page through the server with a mapped suffix ( |
404 for |
The context root is not what you assumed, the application failed to deploy, or the welcome file is missing. |
Check the server log for a deployment error. WildFly, GlassFish and Tomcat use the WAR file name as the context root by
default; keep |
|
The WAR was compiled for a newer Java than the server runs. |
Compile with |
Edits to the page do not appear |
The project stage is |
Set |
|
Another server, or a previous copy of the same one, holds the port. |
Stop it, or start the new server on another port. |
Source: ViewExpiredException (API 4.1) and Mojarra 4.1 README
Where the Books Are Outdated
The first application in the Jakarta Faces 2.0 reference and in the older titles of the bibliography is written for
JSP views (or early Facelets) and javax.faces. Compared with this page:
-
A view was a
.jspfile with<%@ taglib %>directives,<f:view>and<h:form>, mapped through/faces/*or*.jsf. JSP support was removed in Faces 4.0; the view is Facelets XHTML, and mapping theFacesServletis optional. -
Beans were declared in
faces-config.xmlwith<managed-bean>or with@ManagedBean. Both are gone in Faces 4.0 in favour of CDI@Namedandjakarta.enterprise.contextscopes. -
The API was
javax.faces.*and the namespaces werehttp://java.sun.com/jsf/*; they arejakarta.faces.*and thejakarta.faces.htmlURN family, with the old URIs planned for removal in Faces 5.0. -
Faces on a plain servlet container needed only a Faces implementation; today CDI is mandatory for the framework, so Tomcat 11 needs Weld as well, while WildFly and GlassFish need nothing.
References
Related pages elsewhere on this site: Vaadin Reference (the other Java UI framework), ASP.NET Web Forms (the closest sibling: component tree, postback and view state), Thymeleaf Reference (template-based server rendering), Server-Side Web UI Frameworks in Spring Boot and Java Reference.