All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jakarta.faces.flow.FlowHandler Maven / Gradle / Ivy

Go to download

Jakarta Faces defines an MVC framework for building user interfaces for web applications, including UI components, state management, event handing, input validation, page navigation, and support for internationalization and accessibility.

There is a newer version: 4.1.2
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package jakarta.faces.flow;

import java.util.Map;

import jakarta.faces.context.FacesContext;

/**
 * 

* FlowHandler is the main entry point that enables the runtime to * interact with the faces flows feature. {@link jakarta.faces.application.NavigationHandler} uses this class when it * needs to make navigational decisions related to flows. The faces flow feature entirely depends on the * {@link jakarta.faces.lifecycle.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 * {@link jakarta.faces.flow.builder.FlowBuilder} API. Additional means of defining flows may be provided by decorating * the {@link 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 * {@link jakarta.faces.lifecycle.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 the * {@code ClientWindow}. Because Flow instances are immutable, yet the flow stack is * per-user, implementations must make allowance for flow scoped data (managed beans declared to be {@link FlowScoped} * and data stored in the Map returned by {@link #getCurrentFlowScope}) to be fully re-entrant. For * example, consider an application with two flows, A and B, each with a single FlowScoped bean * MyBeanA and MyBeanB, respectively. Entry into flow A causes MyBeanA to become * active. Calling from A into B causes MyBeanB to become active. Calling back into A causes a new instance * of MyBeanA to become active, rather than reactivating the earlier instance of MyBeanA. * *

* *

* 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 {@code true} is used to define the id of the next node to * which control must be passed. If none of the expressions evaluates to {@code true}, 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 {@link 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 * */ public abstract class FlowHandler { /** *

* Components that are rendered by Renderers of component-family jakarta.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 */ public static final String FLOW_ID_REQUEST_PARAM_NAME = "jffi"; /** *

* Components that are rendered by Renderers of component-family jakarta.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 */ public static final String TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME = "jftfdi"; /** *

* Components that are rendered by Renderers of component-family jakarta.faces.OutcomeTarget * must use this constant as the value of the parameter named by {@link #TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME} when * returning from a flow (without entering another flow) using such a component. *

* * @since 2.2 */ public static final String NULL_FLOW = "jakarta.faces.flow.NullFlow"; /** *

* Return the {@code Map} that backs the {@code #{flowScope}} Jakarta Expression Language implicit object or * {@code null} if no flow is currently active. *

* * @return the {@code Map} for this flow scope. * * @since 2.2 */ public abstract Map getCurrentFlowScope(); /** *

* Return the {@link Flow} whose {@code * id} is equivalent to the argument {@code id}, within the scope of the argument {@code definingDocument}. *

* * @param context the {@code FacesContext} for the current request. * * @param definingDocumentId An application unique identifier for the document in which the returned flow is defined. * * @param id the id of a {@link Flow}, unique within the scope of the {@code definingDocument}. * * @throws NullPointerException if any of the parameters are {@code null} * * @return the {@code Flow} for the argument identifiers. * * @since 2.2 */ public abstract Flow getFlow(FacesContext context, String definingDocumentId, String id); /** *

* Add the argument {@link Flow} to the collection of {@code Flow}s known to the current application. The implementation * must be thread safe. *

* * @param context the {@code FacesContext} for the current request. * * @param toAdd the {@code Flow} to add. * * @throws NullPointerException if any of the parameters are {@code null} * * @throws IllegalStateException if there is already a flow with the same {@code id} as the argument {@code Flow} within * the scope of the {@code definingDocument}. * * @throws IllegalArgumentException if the {@code id} of the flow to add is {@code null} or the empty string. * * @throws IllegalArgumentException if the {@code * definingDocumentId} of the {@code toAdd} is {@code null}. * * @since 2.2 */ public abstract void addFlow(FacesContext context, Flow toAdd); /** *

* Return the currently active {@link Flow} for the argument {@code FacesContext}, or {@code null} if no flow is active. * A {@code Flow} must always be associated with exactly one {@link jakarta.faces.lifecycle.ClientWindow}, but a * {@code ClientWindow} may have multiple {@code Flow}s. *

* *
* *

* If {@link #pushReturnMode} had been called with {@code true} as the argument before invoking this method, return the * preceding flow on the stack instead of the actual current flow, or {@code null} if there is no preceding flow. * Otherwise, return the current flow. *

* *
* * @param context the {@code FacesContext} for the current request. * * @throws NullPointerException if any of the parameters are {@code null} * * @return the current {@code Flow} or {@code null} if no flow is active * * @since 2.2 */ public abstract Flow getCurrentFlow(FacesContext context); /** *

* Convenience overload that calls {@link FacesContext#getCurrentInstance()} and then calls through to * {@link #getCurrentFlow(jakarta.faces.context.FacesContext)}. *

* * @return the current {@code Flow} or {@code null} if no flow is active * * @since 2.2 */ public Flow getCurrentFlow() { return getCurrentFlow(FacesContext.getCurrentInstance()); } /** *

* Return the last displayed viewId for the current flow, as returned by * {@link #getCurrentFlow(jakarta.faces.context.FacesContext)}, or {@code null} if there is no current flow. *

* * @param context the {@code FacesContext} for the current request. * * @throws NullPointerException if {@code context} is {@code null} * * @since 2.2 * * @return the last displayed viewId. */ public abstract String getLastDisplayedViewId(FacesContext context); /** *

* Enable the correct handling of navigation when processing a return node. The default * {@link jakarta.faces.application.NavigationHandler} specification requires calling this method before processing the * navigation rules for the flow return, and calling {@link #popReturnMode}, from a {@code finally} block, immediately * afterward. *

* * @param context the {@code FacesContext} for the current request. * * @throws NullPointerException if {@code context} is {@code null}. * * @since 2.2 */ public abstract void pushReturnMode(FacesContext context); /** *

* Enable the correct handling of navigation when processing a return node. The default * {@link jakarta.faces.application.NavigationHandler} specification requires calling this method from a {@code finally} * block, immediately attempting to process the navigation rules in the context of a flow return. *

* * @param context the {@code FacesContext} for the current request. * * @throws NullPointerException if {@code context} is {@code null}. * * @since 2.2 */ public abstract void popReturnMode(FacesContext context); /** *

* Perform a transition in the flow graph for the current user's {@link jakarta.faces.lifecycle.ClientWindow}. Obtain * references to the {@code Flow} instances corresponding to the {@code origin} and {@code destination} arguments. If * the {@code origin Flow} is equal to the {@code destination Flow}, take no action and return {@code null}. Otherwise, * if the {@code outboundCallNode} argument is non-{@code 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 {@code outboundParameters} property of {@code * outboundCallNode} is non-{@code null} and not empty, and the {@code inboundParameters} property of the target flow is * non-{@code 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 {@code destination Flow} is a sub-flow of the {@code * origin Flow} push the {@code destination Flow} onto the flow data structure and return {@code the destination Flow}. * Otherwise, pop the current {@code Flow} from the flow data structure. If the {@code destination Flow} is * non-{@code null}, make the {@code * destination 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 its * {@code setValue} method, passing the value from evaluatedParams. *

* *
* * @param context the {@code FacesContext} for the current request. * * @param sourceFlow the current {@code Flow}, or {@code null} if there is no source flow. * * @param targetFlow the destination {@code Flow}, or {@code null} if there is no destination flow. * * @param outboundCallNode the flow call node causing this transition, or {@code null} if this transition is not caused * by a flow call. * * @param toViewId the viewId of the view being displayed as a result of this transition. This parameter makes it * possible to implement {@link #getLastDisplayedViewId}. * * @throws NullPointerException if {@code context} or {@code toViewId} is {@code null}. * * * @since 2.2 */ public abstract void transition(FacesContext context, Flow sourceFlow, Flow targetFlow, FlowCallNode outboundCallNode, String toViewId); /** *

* 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 * {@link #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 of {@link #TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME}. If * toFlowDocumentId is null, take no action and return. Otherwise, let sourceFlow be the * return from {@link #getCurrentFlow(jakarta.faces.context.FacesContext)}. A null value indicates there is * no current flow, which will be the case if this navigation is trying to enter a flow. If flowId is not * null and toFlowDocumentId is not equal to the value of {@link #NULL_FLOW}, let * targetFlow be the result of calling * {@link #getFlow(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 calling {@link Flow#getFlowCall} on the * sourceFlow, passing targetFlow as the argument. Otherwise, targetFlow and * flowCallNode must remain null, indicating that this is a flow return. Call * {@link FacesContext#getViewRoot()} and let toViewId be the the return from calling * {@link jakarta.faces.component.UIViewRoot#getViewId} on it. *

* *

* Call, {@link #transition}, passing the arguments gathered in the preceding algorithm. *

* *
* * @since 2.2 * * @param context the {@code FacesContext} for the current request. * * @throws NullPointerException if {@code context} is {@code null}. */ public abstract void clientWindowTransition(FacesContext context); /** *

* Return {@code true} if and only if the flow referenced by the argument {@code definingDocument} and {@code id} is * currently active. *

* * @param context the {@code FacesContext} for the current request. * * @param definingDocument An application unique identifier for the document in which the returned flow is defined. * * @param id the id of a {@link Flow}, unique within the scope of the {@code definingDocument}. * * @throws NullPointerException if any of the parameters are {@code null} * * @return true if and only if the referenced flow is active * * @since 2.2 */ public abstract boolean isActive(FacesContext context, String definingDocument, String id); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy