Class FlowHandler
FlowHandler is the main entry point that enables the runtime to
interact with the faces flows feature. NavigationHandler
uses this class when it
needs to make navigational decisions related to flows. The faces flow feature entirely depends on the
ClientWindow
feature and also on CDI.
Defining Flows
The implementation must support defining faces flows using the <flow-definition>
element as
specified in the Application Configuration Resources XML Schema Definition, or by using the
FlowBuilder
API. Additional means of defining flows may be provided by decorating
the FlowHandlerFactory
.
Managing Flows
The singleton instance of this class must be thread safe, and therefore must not store any per-user state. Flows are, however, traversed in a per-user manner, and must be associated with the current
ClientWindow
. Furthermore, Flows may be nested. These requirements strongly suggest managing the flows with a stack-like runtime data structure, stored in a per-user fashion and associated with theClientWindow
. Because Flow instances are immutable, yet the flow stack is per-user, implementations must make allowance for flow scoped data (managed beans declared to beFlowScoped
and data stored in theMap
returned bygetCurrentFlowScope()
) to be fully re-entrant. For example, consider an application with two flows, A and B, each with a singleFlowScoped
beanMyBeanA
andMyBeanB
, respectively. Entry into flow A causesMyBeanA
to become active. Calling from A into B causesMyBeanB
to become active. Calling back into A causes a new instance ofMyBeanA
to become active, rather than reactivating the earlier instance ofMyBeanA
.The Flow Graph
Prior versions of the specification defined a flow graph but the only kind of node in the graph was a VDL view. The Faces Flow feature currently defines the following node types.
View
This is the regular Jakarta Faces VDL View that has been in the specification since the beginning.
Switch
This is a list of Jakarta Expression Language expressions. When control is passed to a switch node, each expression in the list is evaluated and the first one that returns
true
is used to define the id of the next node to which control must be passed. If none of the expressions evaluates totrue
, control passes to the specified default id.Return
This node type specifies an outcome that is returned to the calling flow.
Method Call
This node type allows invocation of arbitrary application logic at any point in the executiong of the flow. An outcome can be specified that will cause a navigation case to be navigated to after the method has been invoked.
Faces Flow Call
This node type allows one flow to call another flow. The calling flow remains active and is not exited until control returns from the called flow.
Edges in the graph are defined by the existing Jakarta Faces navigation rule system.
Flows and Model Objects
Managed beans annotated with the CDI annotation
FlowScoped
are created lazily, when referenced, after a user agent's entry into the named scope, and must be made available for garbage collection when the user agent leaves the flow.The
flowScope
Jakarta Expression Language implicit object is also available to store values in the "current" slope. Values stored in this scope must be made available for garbage collection when the user agent leaves the flow.
- Since:
- 2.2
-
Field Summary
Modifier and TypeFieldDescriptionstatic final String
Components that are rendered byRenderers
of component-familyjakarta.faces.OutcomeTarget
must use this constant as the parameter name for a parameter representing the flow id of the flow that this component will cause to be entered.static final String
Components that are rendered byRenderers
of component-familyjakarta.faces.OutcomeTarget
must use this constant as the value of the parameter named byTO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME
when returning from a flow (without entering another flow) using such a component.static final String
Components that are rendered byRenderers
of component-familyjakarta.faces.OutcomeTarget
must use this constant as the parameter name for a parameter representing the defining document id of the flow that this component will cause to be entered. -
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionabstract void
addFlow
(FacesContext context, Flow toAdd) Add the argumentFlow
to the collection ofFlow
s known to the current application.abstract void
clientWindowTransition
(FacesContext context) Allow for flow transitions in the case of components rendered by the renderers from component-familyjakarta.faces.OutcomeTarget
.Convenience overload that callsFacesContext.getCurrentInstance()
and then calls through togetCurrentFlow(jakarta.faces.context.FacesContext)
.abstract Flow
getCurrentFlow
(FacesContext context) Return theMap
that backs the#{flowScope}
Jakarta Expression Language implicit object ornull
if no flow is currently active.abstract Flow
getFlow
(FacesContext context, String definingDocumentId, String id) Return theFlow
whoseid
is equivalent to the argumentid
, within the scope of the argumentdefiningDocument
.abstract String
getLastDisplayedViewId
(FacesContext context) Return the last displayed viewId for the current flow, as returned bygetCurrentFlow(jakarta.faces.context.FacesContext)
, ornull
if there is no current flow.abstract boolean
isActive
(FacesContext context, String definingDocument, String id) Returntrue
if and only if the flow referenced by the argumentdefiningDocument
andid
is currently active.abstract void
popReturnMode
(FacesContext context) Enable the correct handling of navigation when processing a return node.abstract void
pushReturnMode
(FacesContext context) Enable the correct handling of navigation when processing a return node.abstract void
transition
(FacesContext context, Flow sourceFlow, Flow targetFlow, FlowCallNode outboundCallNode, String toViewId) Perform a transition in the flow graph for the current user'sClientWindow
.
-
Field Details
-
FLOW_ID_REQUEST_PARAM_NAME
Components that are rendered by
Renderers
of component-familyjakarta.faces.OutcomeTarget
must use this constant as the parameter name for a parameter representing the flow id of the flow that this component will cause to be entered.- Since:
- 2.2
- See Also:
-
TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME
Components that are rendered by
Renderers
of component-familyjakarta.faces.OutcomeTarget
must use this constant as the parameter name for a parameter representing the defining document id of the flow that this component will cause to be entered.- Since:
- 2.2
- See Also:
-
NULL_FLOW
Components that are rendered by
Renderers
of component-familyjakarta.faces.OutcomeTarget
must use this constant as the value of the parameter named byTO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME
when returning from a flow (without entering another flow) using such a component.- Since:
- 2.2
- See Also:
-
-
Constructor Details
-
FlowHandler
public FlowHandler()
-
-
Method Details
-
getCurrentFlowScope
Return the
Map
that backs the#{flowScope}
Jakarta Expression Language implicit object ornull
if no flow is currently active.- Returns:
- the
Map
for this flow scope. - Since:
- 2.2
-
getFlow
Return the
Flow
whoseid
is equivalent to the argumentid
, within the scope of the argumentdefiningDocument
.- Parameters:
context
- theFacesContext
for the current request.definingDocumentId
- An application unique identifier for the document in which the returned flow is defined.id
- the id of aFlow
, unique within the scope of thedefiningDocument
.- Returns:
- the
Flow
for the argument identifiers. - Throws:
NullPointerException
- if any of the parameters arenull
- Since:
- 2.2
-
addFlow
Add the argument
Flow
to the collection ofFlow
s known to the current application. The implementation must be thread safe.- Parameters:
context
- theFacesContext
for the current request.toAdd
- theFlow
to add.- Throws:
NullPointerException
- if any of the parameters arenull
IllegalStateException
- if there is already a flow with the sameid
as the argumentFlow
within the scope of thedefiningDocument
.IllegalArgumentException
- if theid
of the flow to add isnull
or the empty string.IllegalArgumentException
- if thedefiningDocumentId
of thetoAdd
isnull
.- Since:
- 2.2
-
getCurrentFlow
Return the currently active
Flow
for the argumentFacesContext
, ornull
if no flow is active. AFlow
must always be associated with exactly oneClientWindow
, but aClientWindow
may have multipleFlow
s.If
pushReturnMode(jakarta.faces.context.FacesContext)
had been called withtrue
as the argument before invoking this method, return the preceding flow on the stack instead of the actual current flow, ornull
if there is no preceding flow. Otherwise, return the current flow.- Parameters:
context
- theFacesContext
for the current request.- Returns:
- the current
Flow
ornull
if no flow is active - Throws:
NullPointerException
- if any of the parameters arenull
- Since:
- 2.2
-
getCurrentFlow
Convenience overload that calls
FacesContext.getCurrentInstance()
and then calls through togetCurrentFlow(jakarta.faces.context.FacesContext)
.- Returns:
- the current
Flow
ornull
if no flow is active - Since:
- 2.2
-
getLastDisplayedViewId
Return the last displayed viewId for the current flow, as returned by
getCurrentFlow(jakarta.faces.context.FacesContext)
, ornull
if there is no current flow.- Parameters:
context
- theFacesContext
for the current request.- Returns:
- the last displayed viewId.
- Throws:
NullPointerException
- ifcontext
isnull
- Since:
- 2.2
-
pushReturnMode
Enable the correct handling of navigation when processing a return node. The default
NavigationHandler
specification requires calling this method before processing the navigation rules for the flow return, and callingpopReturnMode(jakarta.faces.context.FacesContext)
, from afinally
block, immediately afterward.- Parameters:
context
- theFacesContext
for the current request.- Throws:
NullPointerException
- ifcontext
isnull
.- Since:
- 2.2
-
popReturnMode
Enable the correct handling of navigation when processing a return node. The default
NavigationHandler
specification requires calling this method from afinally
block, immediately attempting to process the navigation rules in the context of a flow return.- Parameters:
context
- theFacesContext
for the current request.- Throws:
NullPointerException
- ifcontext
isnull
.- Since:
- 2.2
-
transition
public abstract void transition(FacesContext context, Flow sourceFlow, Flow targetFlow, FlowCallNode outboundCallNode, String toViewId) Perform a transition in the flow graph for the current user's
ClientWindow
. Obtain references to theFlow
instances corresponding to theorigin
anddestination
arguments. If theorigin Flow
is equal to thedestination Flow
, take no action and returnnull
. Otherwise, if theoutboundCallNode
argument is non-null
save aside the outbound parameters. For discussion evaluatedParams is a data structure that stores the evaluated values of any outbound parameters. It is necessary to evaluate these values before popping any flow scopes because the values may refer to scoped instances that need to be passed to the target flow, but will not be available once the new scope is activated. Save aside the outbound parameters using the following algorithm.If the
outboundParameters
property ofoutboundCallNode
is non-null
and not empty, and theinboundParameters
property of the target flow is non-null
and not empty, for each entry in the outbound parameters whose name matches an entry in the inbound parameters, evaluate the value of the parameter, and put the evaluated value into evaluatedParams under the corresponding name. Otherwise, consider evaluatedParams to be empty.If the
destination Flow
is a sub-flow of theorigin Flow
push thedestination Flow
onto the flow data structure and returnthe destination Flow
. Otherwise, pop the currentFlow
from the flow data structure. If thedestination Flow
is non-null
, make thedestination Flow
the current flow, pushing it onto the data structure. If evaluatedParams is not empty, for each entry, find the corresponding parameter in the target flow's inbound parameters and call itssetValue
method, passing the value from evaluatedParams.- Parameters:
context
- theFacesContext
for the current request.sourceFlow
- the currentFlow
, ornull
if there is no source flow.targetFlow
- the destinationFlow
, ornull
if there is no destination flow.outboundCallNode
- the flow call node causing this transition, ornull
if this transition is not caused by a flow call.toViewId
- the viewId of the view being displayed as a result of this transition. This parameter makes it possible to implementgetLastDisplayedViewId(jakarta.faces.context.FacesContext)
.- Throws:
NullPointerException
- ifcontext
ortoViewId
isnull
.- Since:
- 2.2
-
clientWindowTransition
Allow for flow transitions in the case of components rendered by the renderers from component-family
jakarta.faces.OutcomeTarget
. These transitions must happen at the front of the request processing lifecycle due to the HTTP GET based nature of such components. Therefore, this method is called from the restore view phase of the lifecycle.Let flowId be the value in the request parameter map for the parameter whose name is given by the value of
FLOW_ID_REQUEST_PARAM_NAME
. Let toFlowDocumentId be the value in the request parameter map for the paramater whose name is given by the value ofTO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME
. If toFlowDocumentId isnull
, take no action and return. Otherwise, let sourceFlow be the return fromgetCurrentFlow(jakarta.faces.context.FacesContext)
. Anull
value indicates there is no current flow, which will be the case if this navigation is trying to enter a flow. If flowId is notnull
and toFlowDocumentId is not equal to the value ofNULL_FLOW
, let targetFlow be the result of callinggetFlow(jakarta.faces.context.FacesContext, java.lang.String, java.lang.String)
, passing toFlowDocumentId and flowId as the last two arguments, respectively. If the result is non-null
, let flowCallNode be the return from callingFlow.getFlowCall(jakarta.faces.flow.Flow)
on the sourceFlow, passing targetFlow as the argument. Otherwise, targetFlow and flowCallNode must remainnull
, indicating that this is a flow return. CallFacesContext.getViewRoot()
and let toViewId be the the return from callingUIViewRoot.getViewId()
on it.Call,
transition(jakarta.faces.context.FacesContext, jakarta.faces.flow.Flow, jakarta.faces.flow.Flow, jakarta.faces.flow.FlowCallNode, java.lang.String)
, passing the arguments gathered in the preceding algorithm.- Parameters:
context
- theFacesContext
for the current request.- Throws:
NullPointerException
- ifcontext
isnull
.- Since:
- 2.2
-
isActive
Return
true
if and only if the flow referenced by the argumentdefiningDocument
andid
is currently active.- Parameters:
context
- theFacesContext
for the current request.definingDocument
- An application unique identifier for the document in which the returned flow is defined.id
- the id of aFlow
, unique within the scope of thedefiningDocument
.- Returns:
- true if and only if the referenced flow is active
- Throws:
NullPointerException
- if any of the parameters arenull
- Since:
- 2.2
-