X

JSF 2.2 Faces Flow - @FlowScoped, #{flowScope}, @FlowDefinition (TOTD #198)

Guest Author


JavaServer Faces 2.2 is more evolutionary than it is revolutionary.
This is by design as JSF 2.0 added a whole bunch of new features as
part of the Java EE 6 platform. The Preface 1 from the href="http://download.oracle.com/otndocs/jcp/jsf-2_2-pr-spec/index.html">JSF
2.2 Public Review specification provides a list of changes
between JSF 2.1 and 2.2. There are several changes coming in JSF 2.2
but the href="http://java.net/jira/secure/IssueNavigator.jspa?mode=hide&requestId=11471">big
ticket items are:
  • Faces Flow
  • Resource Library Contract
  • HTML5 Friendly Markup


This Tip Of The Day (TOTD) will
explain href="http://javaserverfaces-spec-public.java.net/nonav/proposals/JAVASERVERFACES_SPEC_PUBLIC-730/proposal.txt">Faces
Flow. Section 7.5 and 11.4.3 in the specification introduce
the feature.



Faces Flow provides an encapsulation of related views/pages with an
application defined entry and exit points. For example, a check out
cart can consist of cart page, credit card details page, shipping
address page, and confirmation page. All these pages, along with
required resources and beans, can be packaged together as a module
which can then be reused in other applications.



Each flow has a well-defined entry and exit point that have been
assigned some application specific meaning by the developer. Usually
the objects in a faces flow are designed to allow the user to
accomplish a task that requires input over a number of different
views. In our case, the navigation between pages for selecting
items, entering shipping address, credit card details, and
confirmation page would make a flow. All the pages and objects that
deal with the checking out process can be composed as modules. An
application thus become a collection of flows instead of just views.



It takes the best part of other flow-based technologies such as ADF
Task Flow, Spring Web Flow, and Apace MyFaces CODI and standardizes
in JSF 2.2.



What is the need ?



Imagine a multi-page shopping cart with one page for selecting the
items, a second page for shipping options, a third page for entering
credit card details, and a fourth page for final confirmation.
Managed Beans can be used to capture the data, session scope
variables pass information between pages, button clicks can be used
to invoke the business logic in backing EJBs, and (conditional)
navigation rules can be defined to go from one page to another.
There are a few issues with this approach:
  • This flow of sequence will typically be part of a bigger
    application. However an application, typically with several
    pages, is one large flow and everything is visible with no
    logical partitioning.
  • The flow of pages or views cannot be encapsulated as a logical
    unit and thus cannot be reused, e.g. incorporated into another
    bigger flow easily.
  • The lowest logical granularity is a page. The only way to
    invoke application logic is to tie it to a UI component
    activated by the user in a page. Business logic cannot be
    invoked without any user initiated action.
  • Same flow cannot be opened in multiple windows because session
    scoped variables are used to pass information between pages. CDI
    defines @ConversationScoped but that is only part
    of the solution.

  • There is no scope defined that can span multiple pages but
    less than a session.

Faces Flow provide a solution to the issues mentioned above.



What's new in JSF 2.2 for flows ?



The flow of application is no longer restricted to flow between
pages but instead defined as flow between "nodes". There are five
different types of nodes:
  • View: Any JSF page in the application

  • Method Call: Invoke application logic from flow graph via an
    EL

  • Switch: Navigation decisions in the flow graph based on
    boolean EL

  • Flow Call: Call another flow with parameters and receive
    return values

  • Flow Return: Return to the calling flow


The nodes define the entry and exit points of a flow.



Two new annotations are introduced:
  • @FlowScoped is a CDI scope that defines the scope
    of bean in the specified flow. This enables automatic
    activation/passivation of the bean when the scope is
    entered/exited.
  • @FlowDefinition is a class level annotation that
    allows the flow definition to be defined using the fluent FlowBuilder
    API.


A new EL object, #{flowScope}, for flow local storage
is also introduced. This maps to facesContext.getApplication().getFlowHandler().getCurrentFlowScope().



How are flows packaged ?



Flows can be packaged in JAR files or in directories.



JAR packaging requires flows to be explicitly declared in META-INF/faces-config.xml
in the JAR file. Flow nodes are packaged in META-INF/flows/<flowname>
where <flowname> is a JAR directory entry whose
name is identical to that of a flow id in the corresponding faces-config.xml.
@FlowScoped and @FlowDefinition beans
must be packaged in the JAR file and accompanied by META-INF/beans.xml.




A sample JAR file looks like:


META-INF/faces-config.xml
META-INF/flows/flow1/entry.xhtml
META-INF/flows/flow1/next.xhtml
META-INF/flows/flow1/end.xhtml
META-INF/flows/flow2/start.xhtml
META-INF/flows/flow2/next.xhtml
META-INF/flows/flow2/end.xhtml
META-INF/beans.xml
org/glassfish/sample/MyFlow1Bean.class
org/glassfish/sample/MyFlow2Bean.class
org/glassfish/sample/MyFlowDefintion.class

Flows packaged in directories use convention-over-configuration. The
conventions are:
  • Every View Declaration Language file in that directory is a
    view node of that flow.
  • The start node of the flow is the view whose name is the same
    as the name of the flow.
  • Navigation among any of the views in the directory is
    considered to be within the flow.
  • Navigation to a view outside of that directory is considered
    to be an exit of the flow.
  • Optional <flowname>-flow.xml that
    represents the flow definition. The rules in this file overrides
    the conventions described above.

A sample directory looks like:

flow1/flow1.xhtml
flow1/flow1a.xhtml
flow1/flow1b.xhtml
flow2/flow2-flow.xml
flow2/flow2.xhtml
flow2/flow2a.xhtml
flow2/flow2b.xhtml
WEB-INF/...

Show me the code!



Lets try a sample now!



The source code for the two samples explained below can be href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/e677acaf070aa9202e5145f03cba3568/totd198_flow.zip">downloaded
here. A complete explanation of the sample including the code
walk-through is shown in the video:






This will run on href="http://dlc.sun.com.edgesuite.net/glassfish/4.0/promoted/glassfish-4.0-b72.zip">GlassFish
4.0 b72. For now, you'll need to replace glassfish/modules/javax.faces.jar
with href="https://maven.java.net/content/groups/public/org/glassfish/javax.faces/2.2.0-SNAPSHOT/javax.faces-2.2.0-20130126.094249-235.jar">javax.faces-2.2.0-SNAPSHOT.jar
and replacing glassfish/modules/javax.el.jar with href="http://search.maven.org/remotecontent?filepath=org/glassfish/javax.el/3.0-b03/javax.el-3.0-b03.jar">javax-el-3.0-b03.jar.
This JARs will soon be integrated in the GlassFish build. Ah, the
joys of bleeding edge development!

Join the discussion

Comments ( 17 )
  • vanuatoo Tuesday, January 29, 2013

    Cool. It's sad that it took such a long time to standardize such a natural thing. I've implemented this in my servlet-based framework back in 2005.


  • Ed Burns Tuesday, January 29, 2013

    I just committed a change to rename the XML element for <faces-flow-definition> to just be <flow-definition>.


  • Sree Ramakrishna Saturday, February 2, 2013

    Another good news for Java (or Java EE 6) web-application developers

    JSF 2.x is getting matured for modern web-application.

    The face flow helps a lot because JSF 2.x has become one of most valued technology/web-framework. Spring/Struts/Servlets is not a good choice for modern web-apps.


  • SreeRama Saturday, February 2, 2013

    Vanuatoo, Nice. It would be good if you post and share to public.

    It may be sad for some one, but now it is required feature in JSF 2.x to make happy many and new web developers.


  • Jannis Elgner Tuesday, February 5, 2013

    Thanks for the great post.

    I get an WELD-001303 No active contexts for scope running it on the provided environment. The constructor of Flow1Bean is invoked, after that a proxy is invoked and after that i get the exception I only changed the information which Ed Burns wrote.

    Thanks in advance,

    Jannis Elgner


  • guest Tuesday, February 5, 2013

    Great


  • Arun Gupta Tuesday, February 5, 2013

    Jannie,

    Are you using 2.2.0-SNAPSHOT or 2.2.0-m08 ?


  • Jannis Elgner Tuesday, February 5, 2013

    I tried both in serveral combinations but now i got it working. I changed 2.2.0-SNAPSHOT to 2.2.0-20130126.094249-235 in the pom of your project-sources.

    Thank you!!


  • Arun Gupta Wednesday, February 6, 2013

    Jannis,

    The APIs are evolving fast and glad you got it working!

    Arun


  • guest Thursday, February 28, 2013

    Do you have an example of a jsf component that can drive the flow rather than a page? i.e: On a page there is a component that specifies that it would start flow1 and on that page you'd see the output that is the first page of flow1 in the area allocated to the component. Then within the component that area gets replaced with 2nd page of flow1 etc but the outer page remains the same.


  • Arun Gupta Sunday, March 3, 2013

    I've asked Ed Burns to take a look at your comment and he'll likely respond back.


  • guest Sunday, March 3, 2013

    Just fyi that component would have to reset to first page if any of it's inputs changed. Also first page should be driven by first action of the flow vs a page that way you get to populate the first page of the flow in the flow vs from just inputs and also based on the inputs you may chose to navigate to a different start view state in the flow.. It may already work this way but I wanted to make sure this was possible.


  • Aditya D G Wednesday, July 3, 2013

    I am unable to deploy the application in glassfish which is of version mentioned in the video.Can any one please help me in deploying.

    I googled and found that i have to place the war file autodeploy folder. I tried that but it didnt work.


  • Aditya D G Friday, August 16, 2013

    Hi Arun.

    I deployed the application but navigation between flows is not taking place. Moreover i am getting a compiler error if @FlowDefnition is at the class level in the example, if used the specific version jars you mentioned in the example. I moved that annotation to method level and deployed the application. I am able to deploy but when clicked on any of the buttons to enter into a flow, it is not going.

    Please help me.


  • guest Monday, August 26, 2013

    Faces Flow is very helpful for real world project. Happy it is in feature list now


  • Arun Gupta Monday, September 2, 2013

    Adtiya D G

    Check out completed Faces Flow sample at:

    https://github.com/arun-gupta/javaee7-samples/tree/master/jsf

    Let me know if they don't work on GlassFish 4.

    Cheers

    Arun


  • guest Monday, September 9, 2013

    Hi Arun.

    Faceflow is great as it can solve real flow situation.

    Do the faces flow also support subflow?

    Consider below scenario:

    there are 2 flows:

    customer/search_customer.xhtml

    customer/customer_details.xhtml

    flowB/seach.xhtml

    flowB/edit_details.xhtml

    here is the flow order:

    search_customer.xhtml --> edit customer_details.xhtml --> goto flow B (edit and then save) --> customer_details.xhtml in edit mode.

    assume the result of the flowB require to pass to flowA.

    The entry point of the customer flow is customer.xhtml

    The entry point of the flow B flow is search.xhtml

    Do I require to set 1 more flow definition to achieve the above situation?

    Please help.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.