Faces Flow in JSF 2.2 - Part 1: Basics: For Live Training On JSF 2, Primefaces, or Other
Faces Flow in JSF 2.2 - Part 1: Basics: For Live Training On JSF 2, Primefaces, or Other
Overview
Motivation
• Modularity
– Pages and beans can self contained
• Wizard-like structures
– Fits well with a common approach to many Web activities. Similarly, the
Oracle Java EE tutorial says that it is analogous to a subroutine, with
• A well defined entry point, list of parameters, and return value.
• A scope, allowing information to be available only during the invocation of
the flow and to not consume resources once the flow returns.
• The ability to call other flows before returning.
• Less server memory
– Compared to session scope, beans are removed from memory much sooner:
when user leaves the flow.
• Not fooled by multiple browser tabs or windows
– Each tab or window is considered to be a separate flow. This is in contrast
to session scope, which is easily confused by multiple tabs or windows.
8
Setup
• Eclipse users
– Declare project as Dynamic Web Project for Glassfish 4
• Integrate Glassfish 4 inside Eclipse (see next slide)
• Users of other IDEs
– Declare project as Java EE 7 Web project (details vary)
• Faces Flow uses CDI
– So, you need a Java EE 7 server, or you must add CDI to
a servlet engine like Tomcat.
• See upcoming slides on adding CDI to Tomcat
• Glassfish requires an empty beans.xml file
– Needs only valid start and end tags, but no body.
• Java-based configuration fails without the file.
9
12
Using CDI in Tomcat
• Very brief summary
– Add <Resource> to bottom of Tomcat’s context.xml
– Put weld-servlet.jar in WEB-INF/lib of your app
– Add <resource-env-ref> to web.xml of your app
• Full details and sample files
– http://www.jsf2.com/using-cdi-and-jsf-2.2-faces-flow-in-tomcat/
• Notes
– The exact same app will not run unchanged in both
Tomcat and a Java EE 7 server, since apps with weld-
servlet.jar will not run in Glassfish 4.
• However, all of the faces flow code is identical, and both
Glassfish and Tomcat versions of the app for this tutorial
section can be downloaded from the JSF 2 tutorial at
13 http://www.coreservlets.com/JSF-Tutorial/jsf2/
Details
• Standard files and corresponding outcomes
– Folder name matching flow name with empty XML file
• someFlow/someFlow-flow.xml
– A default starting page in the folder
• someFlow/someFlow.xhtml
• Outcome of "someFlow" enters flow and starts at this page
• If in flow, outcome of "someFlow" goes to this page
– Any other files in the folder
• someFlow/other.xhtml
• If in flow, outcome of "other" goes to this page.
• Not reachable from outside the flow.
– A return page outside the folder
• someFlow-return.xhtml
16
• Outcome of "someFlow-return" exits flow and goes to this page
Implicit Navigation:
Flow Diagram
outside-page.xhtml
(flowname folder must contain
flowname/flowname.xhtml flowname-flow.xml)
flowname-return.xhtml
flowname/foo.xhtml flowname/bar.xhtml
Legend
17
This file must exist, but can be totally empty. Not even start or end tags are needed.
An outcome of "flow1" causes the flow to start, and this page to be displayed. For example,
<h:commandButton … action="flow1"/> or <h:commandButton … action="#{someBean.someMethod}"/>, where
someMethod returns "flow1".
From within the flow, outcomes of "page2" and "page3" invoke these pages.
The pages are not accessible from outside the flow: you must begin flows at the start page.
In order for Java-based flow configuration (in Faces Flow Part 2) to work on Glassfish 4, this file
must exist, and must have valid start and end tags. No content inside the tags is needed.
From within the flow, an outcome of "flow1-return" invokes this page. That outcome also results in the
flowScope variable being cleared and flow-scoped beans being made inaccessible and available for
garbage collection. (The flowScope variable and flow-scoped beans are discussed in the next section.)
This page cannot be reached from within the flow by using an outcome. Of course, a normal hypertext
link will still work. And, we will see that when you use an XML flow-configuration file, you can designate
18 as many return pages as you want.
Reminder: Static Navigation
• Usual case: run Java code returning String
– <h:commandButton action="#{bean.doNav}" .../>
– <h:commandLink action="#{bean.doNav}" .../>
• Suppose doNav is very simple
public String doNav() {
return("result-page");
}
• Equivalent case: specify outcome directly
– <h:commandButton action="result-page" .../>
– <h:commandLink action="result-page" .../>
19
Flow1 Example:
Starting the Flow
• Link from home page
<h:form>
<h:commandLink value="Flow 1." action="flow1"/>
</h:form>
• flow1/flow1.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
template="/templates/flow1-template.xhtml">
</ui:composition>
I use templates in these examples because so many of the pages have similar layouts.
However, there is no particular tie between faces flow and templates.
20
Flow1 Template File (Excerpt)
...
<h:form>
<ul>
<li><h:commandButton value="Page 1" action="flow1"/><br/>
First page in flow (implicit flow start page).</li>
<li><h:commandButton value="Page 2" action="page2"/><br/>
Second page in flow (implicit flow navigation).</li>
<li><h:commandButton value="Page 3" action="page3"/><br/>
Third page in flow (implicit flow navigation).</li>
<li><h:commandButton value="Return Page" action="flow1-return"/><br/>
Page outside flow (implicit flow return page).</li>
<li><h:commandButton value="Home Page (FAILS)" action="home"/><br/>
Pages outside flow cannot be reached by using JSF outcomes,
even if you explicitly map the outcomes in faces-config.xml.</li>
<li><a href="#{request.contextPath}/index.jsf">Home Page (SUCCEEDS)</a><br/>
However, of course it still works to use a a regular hypertext link
to pages outside the flow.</li>
</ul>
</h:form>
...
21
22
Flow1 Page 2
flow1/page2.xhtml
• Invoked by
– <h:commandButton … action="page2"/>
• From inside the flow only
23
Flow1 Page 3
flow1/page3.xhtml
• Invoked by
– <h:commandButton … action="page3"/>
• From inside the flow only
24
Flow1 Return Page
flow1-return.xhtml
• Invoked by
– <h:commandButton … action="flow1-return"/>
• From inside or outside the flow
25
Flow-Scoped Beans
and the flowScope
Variable
Customized Java EE Training: http://courses.coreservlets.com/
Java 7, Java 8, JSF 2, PrimeFaces, Android, JSP, Ajax, jQuery, Spring MVC, RESTful Web Services, GWT, Hadoop.
Developed and taught by well-known author and developer. At public venues or onsite at your location.
Main Points
• Flow-scoped beans have a bigger scope
than view-scoped beans
– They are available to the same user in all pages in a flow,
rather than for a single page
• Flow-scoped beans have a smaller scope
than session-scoped beans
– The beans go away when user navigates out of flow
• There is a new EL flowScope variable
– That can be used to directly store simple values
• But, flow-scoped beans are usually better
• Flow-scoped beans depend on CDI
– They require a Java EE 7 server or CDI to be added
27 – You must use @Named, not @ManagedBean
Flow2 Example:
Annotated Project Layout
From within the flow, outcomes of “confirmation1" and “confirmation2" invoke these pages.
The Flow2Bean and the flowScope variable carry values from earlier in the flow.
An outcome of "flow2" causes the flow to start and this page to be displayed. The Flow2Bean is instantiated
when this page is visited from outside the flow.
From within the flow, an outcome of "flow2-return" invokes this page. That outcome also results in the
flowScope variable being cleared and the flow-scoped Flow2Bean being made inaccessible, removed
from the session, and made available for garbage collection.
28
Flow2Bean (Part 1)
... The ID of the flow to which this bean applies. The ID is usually, but not necessarily always, the folder name.
@Named
@FlowScoped("flow2")
public class Flow2Bean implements Serializable {
private static final long serialVersionUID = 1L;
private String firstName, lastName;
private int pagesViewed = 1;
29
Flow2Bean (Part 2)
The action controller method, as specified by <h:commandButton … action="#{flow2Bean.doFlow}"/>
It randomly chooses a page inside the flow, assuming that the flow folder has confirmation1.xhtml and
confirmation2.xhtml inside of it.
30
Importance of Serializable
• Flow-scoped beans are in the session
– So, like all things in the session, should be Serializable
• For distributed Web apps
• So they can live across server restarts
• If you fail to make session-scoped beans
Serializable
– Tomcat gives mild warning, but it works anyhow (except
they do not persist across server restarts)
• If you fail to make flow-scoped beans
Serializable
– Tomcat fails on app startup with Weld exception
31
33
After filling in
34
Results:
Flow2 Confirmation Pages
• Invoked by outcomes of "confirmation1"
and "confirmation2"
– The flowScope variable and the flow2Bean carry their
values from earlier pages in the flow.
35
Results:
Flow2 Return Page
• Invoked by outcome of "flow2-return"
– The flowScope variable has been cleared and the
flow2Bean has been removed from the session and is no
longer available at #{flow2Bean…}
36
© 2015 Marty Hall
Main Points
• Use flowname/flowname-flow.xml to
– Define the start page
<start-node>startPage</start-node>
<view id="startPage">…</view>
– Define the return page(s) (required)
<flow-return id="some-id">…</flow-return>
– Map outcomes to pages
<view id="another-id">…</view>
– Conditionally map outcomes to pages
<switch id="blah-id">
<case>…</case>
<case>…</case>
<default-outcome>…</default-outcome>
38
</switch>
XML Configuration File:
General Info
• File name and location
– flowname/flowname-flow.xml
• Basic syntax
<?xml version='1.0' encoding='UTF-8'?>
<faces-config … version="2.2">
Same attributes and values as regular faces-config.xml file in JSF 2.2
<flow-definition id="flow-id">
…
These entries are shown in slides in this section
</flow-definition>
</faces-config>
• Reminder
– Even if you do not use the XML file to configure the
flow, the file must still exist (but can be completely
39
empty).
• Default
– If <start-node> is omitted, the usual default of
/flowname/flowname.xhtml is used, as shown in previous
section.
40
Defining the Start Page:
Flow3 Example
• Code
<start-node>startPage</start-node>
<view id="startPage">
<vdl-document>
/flow3/flow3-starting-page.xhtml
</vdl-document>
</view>
• Notes
– From outside page, when outcome "flow3" occurs, the
flow is started and flow3-starting-page.xhtml is invoked
– The name “startPage” above is arbitrary. The only rule is
that name inside <start-node> matches the id of some
41
view that defines the page location.
<flow-return id="first-return-id">
<from-outcome>/outside-page-1</from-outcome>
</flow-return>
<flow-return id="second-return-id">
<from-outcome>/outside-page-2</from-outcome>
</flow-return>
• No default
– At least one return page must be defined.
– When using an XML configuration file, the usual default
return page of flowname-return.xhtml goes away.
42
Defining the Return Pages:
Flow3 Example
• Code
<flow-return id="return-from-flow3">
<from-outcome>
/return-page-for-flow3
</from-outcome>
</flow-return>
<flow-return id="go-home">
<from-outcome>/index</from-outcome>
</flow-return>
• Notes
– It is common to have only a single return page. This
example just illustrates that it is possible to have multiple
43 ones.
44
Mapping Outcomes to Pages:
Flow3 Example
• Code
<view id="confirmation1">
<vdl-document>
/flow3/confirmation-page-1.xhtml
</vdl-document>
</view>
<view id="confirmation3">
<vdl-document>
/flow3/confirmation-page-3.xhtml
</vdl-document>
</view>
• Notes
– No mapping for "confirmation2", so default of
/flow3/confirmation2.xhtml will be used.
45
• Just for illustration: you usually map all pages or map none of them
<if>#{flow3HitCountBean.currentCount eq 1}</if>
<from-outcome>confirmation3</from-outcome>
</case>
<case>
<if>#{flow3HitCountBean.currentCount lt 5}</if>
<from-outcome>confirmation4</from-outcome>
</case>
<default-outcome>confirmation5</default-outcome>
</switch>
• Notes
– The hit-count-bean is separate from the main bean.
– Used <view> to map "confirmation3" to confirmation-page-3.xhtml
– Used defaults for other two pages: confirmation4.xhtml, and confirmation5.xhtml.
48
Flow3Bean
package coreservlets;
import javax.faces.flow.FlowScoped;
import javax.inject.Named;
@Named
@FlowScoped("flow3")
public class Flow3Bean extends Flow2Bean {
private static final long serialVersionUID = 1L;
}
49
FlowHitCount3Bean
...
@Named
@SessionScoped
public class Flow3HitCountBean implements Serializable {
private static final long serialVersionUID = 1L;
private int hitCount;
Note also that If you use @Named instead of @ManagedBean, then you must use the CDI
(javax.enterprise.context) version of SessionScoped, not the JSF version (javax.faces.bean).
With faces flow, you use CDI consistently.
50
Flow3 Configuration File (Part 1)
flow3/flow3-flow.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config
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-facesconfig_2_2.xsd"
version="2.2">
<flow-definition id="flow3">
<start-node>startPage</start-node>
<view id="startPage">
<vdl-document>/flow3/flow3-starting-page.xhtml</vdl-document>
</view>
<flow-return id="return-from-flow3">
<from-outcome>/return-page-for-flow3</from-outcome>
</flow-return>
<flow-return id="go-home">
<from-outcome>/index</from-outcome>
</flow-return>
51
<switch id="confirm">
<case>
<if>#{flow3HitCountBean.currentCount eq 1}</if>
<from-outcome>confirmation3</from-outcome>
</case>
<case>
<if>#{flow3HitCountBean.currentCount lt 5}</if>
<from-outcome>confirmation4</from-outcome>
</case>
<default-outcome>confirmation5</default-outcome>
</switch>
</flow-definition>
52 </faces-config>
Flow3 Start Page
flow3/flow3-starting-page.xhtml
...<h:form>
<h:panelGrid columns="3" styleClass="formTable">
Email address:
<h:inputText value="#{flowScope.email}" id="email"
required="true"
requiredMessage="Must supply email address"/>
<h:message for="email" styleClass="error"/>
<f:facet name="footer">
<h:commandButton value="Random Confirmation Page (via Java)"
action="#{flow3Bean.doFlow}"/><br/>
<h:commandButton value="Confirmation Page Based on Visits (via switch)"
action="confirm"/>
</f:facet>
</h:panelGrid> The "confirm" entry corresponds to the <switch> tag, and, depending on the number of visits, is mapped to "confirmation3",
"confirmation4", or "confirmation5". "confirmation3" is mapped via the <view> tag to confirmation-page-3.xhtml, whereas
53 </h:form>... "confirmation4" and "confirmation5" have the default mappings of confirmation4.xhtml and confirmation5.xhtml.
54
Results: Flow3 Start Page
• Invoked by outcome of "flow3"
– When arriving here from outside flow, the Flow3Bean is
instantiated and placed in the session. The flowScope
variable is empty at this point.
Initial state
After filling in
55
Results:
Flow3 Confirmation Pages
• Invoked by outcomes of "confirmation1",
"confirmation2", and "confirm"
– Pressing the top button on start page runs the doFlow
method, which randomly chooses "confirmation1" or
"confirmation2". Pressing the bottom button sends
"confirm", which is mapped by the switch to
"confirmation3", "confirmation4", and "confirmation5".
The other
four
confirmation
pages are
similar
56
Results:
Flow3 Return Pages
• Invoked by "return-from-flow3" or
"go-home"
– Two return pages are defined in flow3-flow.xml, as
shown earlier.
• The first results in the return page shown below. The
second results in the home page for the flows app.
57
Flow4 Example:
Annotated Project Layout
Start page (as defined with <start-node> and matching <view> in faces-config.xml)
Confirmation pages for outcomes "confirmation1" and "confirmation2" (as defined with <view>)
60
Flow4 Flow Definition
WEB-INF/faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config ... version="2.2">...
<flow-definition id="fourth-flow">
<start-node>startPage</start-node>
<view id="startPage">
<vdl-document>/flow4/a.xhtml</vdl-document>
</view>
<view id="confirmation1">
<vdl-document>/flow4/b.xhtml</vdl-document>
</view>
<view id="confirmation2">
<vdl-document>/flow4/c.xhtml</vdl-document>
</view>
<flow-return id="return-from-flow4">
<from-outcome>/return-page-for-flow4</from-outcome>
</flow-return>
<flow-return id="go-home">
<from-outcome>/index</from-outcome>
</flow-return>
</flow-definition>
61 </faces-config>
Wrap-Up
Questions?
More info:
http://www.coreservlets.com/JSF-Tutorial/jsf2/ – JSF 2.2 tutorial
http://www.coreservlets.com/JSF-Tutorial/primefaces/ – PrimeFaces tutorial
http://courses.coreservlets.com/jsf-training.html – Customized JSF and PrimeFaces training courses
http://coreservlets.com/ – JSF 2, PrimeFaces, Java 7 or 8, Ajax, jQuery, Hadoop, RESTful Web Services, Android, HTML5, Spring, Hibernate, Servlets, JSP, GWT, and other Java EE training