This document gives a rough and incomplete overview of JavaServer Faces (JSF, 2.2, JSR 344).
|
Note
|
The reader supposedly has basic knowledge of Servlets, CDI, XML (including namespaces) and Java EE Application servers. |
One of the goals of JSF is to provide HTML pages to your clients, built on your server. Let’s first see why you can’t do this using simple Java EE servlet technology. Following a simple servlet development, here is what happens:
-
the client (say, the web browser of a user) requests a page from your servlet (say, sends a GET request to http://your-server/some-web-page);
-
the container (sitting on the Java EE application server) directs the request to your servlet;
-
your servlet processes the request, and returns an answer to the client;
-
this answer gets (for example) displayed in the user’s browser.
This works well if you need to return, for example, a simple text to the client. But what if your client expects a nice HTML page in return? You might use the writer in your servlet to write tags manually, but this would be extremely cumbersome and error-prone. One of the benefits of JSF is that it provides a clean solution for this use case.
In JSF, you write a page using the “Facelets” technology. (You can view this as a declarative language similar to HTML.) This page gets interpreted by the container when it detects a request directed to it. The (very high-level) process is as follows.
-
The container builds an intermediate tree from this page: a tree of JSF components.
-
The container calls your code as necessary for validating the input from the user (if any) or obtaining information needed for the response. This possibly modifies the tree of components (e.g. by changing the text associated to some components).
-
Finally, the container renders the tree, which builds an HTML representation of it, and send the resulting data as an HTTP answer to the client.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Greetings page</title>
</head>
<body>
<p>
Hi, <h:outputText value="#{user.name}" />.
</p>
</body>
</html>Assume a client sends an HTTP GET request to your application server, and assume your server is configured for directing that request to this example Facelet page.
-
All unprefixed elements (e.g.
html,head) and simple text will simply be passed through to the client. -
The only special element here is the
outputTextelement, that sits in the JSF namespace (thanks to thehprefix). The container builds a component of typeHtmlOutputTextrepresenting this element. The container knows this by convention: the JSF specification lists JSF tags and their corresponding components. -
This component gets added to the tree of components representing the Facelet page being processed. In this example, the tree is very simple as there is only one explicit JSF component in this page.
-
The container sets the value of the newly created
HtmlOutputTextcomponent to (something like)"#{user.name}". Actually, this represents a “value expression” that will be evaluated by the container at some point in the JSF treatment cycle. -
A managed bean (as understood from the CDI specification) must exist under the name
userfor the evaluation of the"#{user.name}"value expression to work. Assuming such a bean exists, the container will get thenameproperty of theuserbean and put it into the value of theHtmlOutputTextcomponent. -
Finally, the container will render the page, that is, convert it into an equivalent html representation, and send it back to the client as the HTTP answer to its request. Components get rendered to html in different manners depending on their type.
HtmlOutputTextcomponents simply render their value.
Inversion of control JSF implements a (second level of) Inversion of Control (IoC) pattern, supplementary to the usual IoC happening when you build a classical servlet (see Servlets.adoc): you do not control the flow of the code, rather, the container calls your code at specified time points during the JSF treatment cycle.