Editing pass
Edited for grammar, punctuation, spelling, usage, and voice.
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
[[_actions]]
|
||||
== Executing Actions
|
||||
|
||||
This chapter shows you how to use the `action-state` element to control the execution of an action at a point within a flow.
|
||||
This chapter shows you how to use the `action-state` element to control the invocation of an action at a point within a flow.
|
||||
It also shows how to use the `decision-state` element to make a flow routing decision.
|
||||
Finally, several examples of invoking actions from the various points possible within a flow are discussed.
|
||||
|
||||
[[_action_state]]
|
||||
=== Defining Action States
|
||||
|
||||
You can use the `action-state` element when you wish to invoke an action and then transition to another state based on the action's outcomem, as follows:
|
||||
You can use the `action-state` element when you wish to invoke an action and then transition to another state based on the action's outcome, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -21,7 +21,7 @@ You can use the `action-state` element when you wish to invoke an action and the
|
||||
----
|
||||
====
|
||||
|
||||
The following example shows an interview flow that uses the preceding `action-state` above to determine if more answers are needed to complete the interview:
|
||||
The following example shows an interview flow that uses the preceding `action-state` to determine if more answers are needed to complete the interview:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -56,20 +56,20 @@ The following example shows an interview flow that uses the preceding `action-st
|
||||
----
|
||||
====
|
||||
|
||||
After the execution of each action, the `action-state` checks the result to see if it matches a declared transition to another state.
|
||||
That means that, if more than one action is configured, they are executed in an ordered chain until one returns a single result event that matches a state transition out of the action-state while the rest are ignored.
|
||||
After the invocation of each action, the `action-state` checks the result to see if it matches a declared transition to another state.
|
||||
That means that, if more than one action is configured, they are invoked in an ordered chain until one returns a single result event that matches a state transition out of the action-state while the rest are ignored.
|
||||
This is a form of the "`Chain of Responsibility`" (CoR) pattern.
|
||||
|
||||
The result of an action's execution is typically the criteria for a transition out of this state.
|
||||
The result of an action's invocation is typically the criteria for a transition out of this state.
|
||||
You can also test additional information in the current `RequestContext` as part of custom transitional criteria that allow for sophisticated transition expressions that reason on contextual state.
|
||||
|
||||
Note also that an `action-state` (as any other state) can have more on-entry actions that are executed as a list from start to end.
|
||||
Note also that an `action-state` (as any other state) can have more on-entry actions that are invoked as a list from start to end.
|
||||
|
||||
[[_decision_state]]
|
||||
=== Defining Decision States
|
||||
|
||||
You can use the `decision-state` element as an alternative to the `action-state` to make a routing decision using a convenient if-else syntax.
|
||||
The following example shows the `moreAnswersNeeded` state (from the example in the preceding section) now implemented as a decision state instead of an action-state:
|
||||
You can use the `decision-state` element as an alternative to the `action-state` element to make a routing decision by using a convenient if-else syntax.
|
||||
The following example shows the `moreAnswersNeeded` state (from the example in the preceding section), now implemented as a decision state instead of an action-state:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -103,7 +103,7 @@ The following table describes how common return value types are mapped to `Event
|
||||
|`java.lang.Enum`
|
||||
|the `Enum` name
|
||||
|
||||
|any other type
|
||||
|Any other type
|
||||
|success
|
||||
|===
|
||||
|
||||
@@ -125,7 +125,7 @@ The following example invokes a method that returns a boolean value:
|
||||
While writing action code as POJO logic is the most common, there are several other action implementation options.
|
||||
Sometimes, you need to write action code that needs access to the flow context.
|
||||
You can always invoke a POJO and pass it the `flowRequestContext` as an EL variable.
|
||||
Alternatively, you may implement the `Action` interface or extend from the `MultiAction` base class.
|
||||
Alternatively, you can implement the `Action` interface or extend from the `MultiAction` base class.
|
||||
These options provide stronger type safety when you have a natural coupling between your action code and Spring Web Flow APIs.
|
||||
The following sections show examples of each of these approaches.
|
||||
|
||||
@@ -198,7 +198,7 @@ public class CustomMultiAction extends MultiAction {
|
||||
=== Action Exceptions
|
||||
|
||||
Actions often invoke services that encapsulate complex business logic.
|
||||
These services may throw business exceptions that the action code should handle.
|
||||
These services can throw business exceptions that the action code should handle.
|
||||
|
||||
==== Handling a Business Exception with a POJO Action
|
||||
|
||||
@@ -261,7 +261,7 @@ public Event makeBooking(RequestContext context) {
|
||||
|
||||
==== Using an `exception-handler` Element
|
||||
|
||||
In general, it is recommended to catch exceptions in actions and return result events that drive standard transitions.
|
||||
In general, you should catch exceptions in actions and return result events that drive standard transitions.
|
||||
You can also add an `exception-handler` sub-element to any state type with a `bean` attribute that references a bean of type `FlowExecutionExceptionHandler`.
|
||||
This is an advanced option that, if used incorrectly, can leave the flow execution in an invalid state.
|
||||
Consider the built-in `TransitionExecutingFlowExecutionExceptionHandler` as an example of a correct implementation.
|
||||
@@ -336,7 +336,7 @@ The following example shows a state exit action that releases a lock on a record
|
||||
|
||||
==== The `on-end` Element
|
||||
|
||||
The following example shows object locking behavior that is equivalent to the example in the preceding section using flow start and end actions:
|
||||
The following example shows object locking behavior that is equivalent to the example in the preceding section but uses flow start and end actions:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -427,7 +427,7 @@ In this example, the flow transitions to `showResults` when `thingTwo` completes
|
||||
|
||||
==== Streaming Actions
|
||||
|
||||
Sometimes, an Action needs to stream a custom response back to the client.
|
||||
Sometimes, an action needs to stream a custom response back to the client.
|
||||
An example might be a flow that renders a PDF document when handling a print event.
|
||||
This can be achieved by having the action stream the content and then record a status of `Response Complete` status on the `ExternalContext`.
|
||||
The `responseComplete` flag tells the pausing `view-state` not to render the response because another object has taken care of it.
|
||||
@@ -464,7 +464,7 @@ The action renders the PDF and then marks the response as complete.
|
||||
==== Handling File Uploads
|
||||
|
||||
Another common task is to use Web Flow to handle multipart file uploads in combination with Spring MVC's `MultipartResolver`.
|
||||
Once the resolver is set up correctly https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-multipart[as described here] and the submitting HTML form is configured with `enctype="multipart/form-data"`, you can easily handle the file upload in a transition action.
|
||||
Once the resolver is set up correctly, https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-multipart[as described here], and the submitting HTML form is configured with `enctype="multipart/form-data"`, you can handle the file upload in a transition action.
|
||||
|
||||
NOTE: The file upload example shown in the next listing is not relevant when you use Web Flow with JSF.
|
||||
See <<_spring_faces_file_upload>> for details of how to upload files using JSF.
|
||||
|
||||
@@ -8,7 +8,7 @@ By the end of this chapter, you should have a good understanding of language con
|
||||
== What Is a Flow?
|
||||
|
||||
A flow encapsulates a reusable sequence of steps that you can use in different contexts.
|
||||
The following a http://www.jjg.net/ia/visvocab/[Garrett Information Architecture] diagram shows a reference to a flow that encapsulates the steps of a hotel booking process:
|
||||
The following http://www.jjg.net/ia/visvocab/[Garrett Information Architecture] diagram shows a reference to a flow that encapsulates the steps of a hotel booking process:
|
||||
|
||||
image::images/hotels-site.png[]
|
||||
|
||||
@@ -27,7 +27,7 @@ image::images/hotels-site-bookhotel-flow.png[]
|
||||
[[_flow_authoring]]
|
||||
== How Are Flows Authored?
|
||||
|
||||
Flows are authored by web application developers by using a simple XML-based flow definition language.
|
||||
Flows are authored by using a simple XML-based flow definition language.
|
||||
The next steps of this guide walk you through the elements of this language.
|
||||
|
||||
[[_essential_flow_elements]]
|
||||
@@ -45,6 +45,7 @@ There are four essential flow elements:
|
||||
|
||||
Every flow begins with the following root element:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
@@ -56,6 +57,7 @@ Every flow begins with the following root element:
|
||||
|
||||
</flow>
|
||||
----
|
||||
====
|
||||
|
||||
All states of the flow are defined within this element.
|
||||
The first state defined becomes the flow's starting point.
|
||||
@@ -63,22 +65,25 @@ The first state defined becomes the flow's starting point.
|
||||
[[_view_state_element]]
|
||||
=== The `view-state` Element
|
||||
|
||||
Use the `view-state` element to define a step of the flow that renders a view:
|
||||
The `view-state` element defines a step of the flow that renders a view:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<view-state id="enterBookingDetails" />
|
||||
----
|
||||
====
|
||||
|
||||
By convention, a view-state maps its id to a view template in the directory where the flow is located.
|
||||
For example, the state above might render [path]_/WEB-INF/hotels/booking/enterBookingDetails.xhtml_ if the flow itself was located in the [path]_/WEB-INF/hotels/booking_ directory.
|
||||
For example, the preceding state might render `/WEB-INF/hotels/booking/enterBookingDetails.xhtml` if the flow itself was located in the `/WEB-INF/hotels/booking` directory.
|
||||
|
||||
[[_transition_element]]
|
||||
=== The `transition` Element
|
||||
|
||||
Use the `transition` element to handle events that occur within a state:
|
||||
The `transition` element handles events that occur within a state:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
@@ -86,19 +91,22 @@ Use the `transition` element to handle events that occur within a state:
|
||||
<transition on="submit" to="reviewBooking" />
|
||||
</view-state>
|
||||
----
|
||||
====
|
||||
|
||||
These transitions drive view navigations.
|
||||
|
||||
[[_end_state_element]]
|
||||
=== The `end-state` Element
|
||||
|
||||
Use the `end-state` element to define a flow outcome:
|
||||
The `end-state` element defines a flow outcome:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<end-state id="bookingCancelled" />
|
||||
----
|
||||
====
|
||||
|
||||
When a flow transitions to a end-state, it ends and the outcome is returned.
|
||||
|
||||
@@ -151,14 +159,14 @@ Within a flow, there are several points where you can execute actions:
|
||||
* On flow end
|
||||
|
||||
Actions are defined by using a concise expression language.
|
||||
Spring Web Flow uses the Unified EL by default.
|
||||
By default, Spring Web Flow uses the Unified EL.
|
||||
The next few sections cover the essential language elements for defining actions.
|
||||
|
||||
[[_evaluate_element]]
|
||||
=== The `evaluate` Element
|
||||
|
||||
The most-often-used action element is the `evaluate` element.
|
||||
You can use the `evaluate` element to evaluate an expression at a point within your flow.
|
||||
The most often used action element is the `evaluate` element.
|
||||
The `evaluate` element evaluates an expression at a point within your flow.
|
||||
With this single element, you can invoke methods on Spring beans or any other flow variable.
|
||||
The following listing shows an example:
|
||||
|
||||
@@ -173,7 +181,7 @@ The following listing shows an example:
|
||||
[[_evaluate_element_result]]
|
||||
==== Assigning an `evaluate` Result
|
||||
|
||||
If the expression returns a value, that value can be saved in the flow's data model called `flowScope`, as follows:
|
||||
If the expression returns a value, that value can be saved in the flow's data model, called `flowScope`, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -266,7 +274,7 @@ public interface FlowOutcome {
|
||||
[[_input_element]]
|
||||
=== input
|
||||
|
||||
You can use the `input` element to declare a flow input attribute, as follows:
|
||||
The `input` element declares a flow input attribute, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -276,12 +284,12 @@ You can use the `input` element to declare a flow input attribute, as follows:
|
||||
====
|
||||
|
||||
Input values are saved in flow scope under the name of the attribute.
|
||||
For example, the input in the prececing example is saved under a name of `hotelId`.
|
||||
For example, the input in the preceding example is saved under a name of `hotelId`.
|
||||
|
||||
[[_input_element_type]]
|
||||
==== Declaring an Input Type
|
||||
|
||||
Use the `type` attribute to declare the input attribute's type:
|
||||
The `type` attribute declares the input attribute's type:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -295,7 +303,7 @@ If an input value does not match the declared type, a type conversion is attempt
|
||||
[[_input_element_value]]
|
||||
==== Assigning an Input Value
|
||||
|
||||
You can use the `value` attribute to specify an expression to which to assign the input value, as follows:
|
||||
The `value` attribute specifies an expression to which to assign the input value, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -309,7 +317,7 @@ If the expression's value type can be determined, that metadata is used for type
|
||||
[[_input_element_required]]
|
||||
==== Marking an input as required
|
||||
|
||||
You can use the `required` attribute to enforce the input is not null or empty, as follows:
|
||||
The `required` attribute enforces that the input is not null or empty, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -321,7 +329,7 @@ You can use the `required` attribute to enforce the input is not null or empty,
|
||||
[[_output_element]]
|
||||
=== The `output` Element
|
||||
|
||||
You can use the `output` element to declare a flow output attribute.
|
||||
The `output` element declares a flow output attribute.
|
||||
Output attributes are declared within end-states that represent specific flow outcomes.
|
||||
The following listing defines an `output` element:
|
||||
|
||||
@@ -340,7 +348,7 @@ For example, the output in the preceding example would be assigned the value of
|
||||
[[_output_element_value]]
|
||||
==== Specifying the Source of an `output` Value
|
||||
|
||||
You can use the `value` attribute to denote a specific output value expression, as follows:
|
||||
The `value` attribute denotes a specific output value expression, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -401,7 +409,7 @@ Any `@Autowired` transient references the variable holds are also rewired when t
|
||||
[[_var_element]]
|
||||
=== The `var` Element
|
||||
|
||||
You can use the `var` element to declare a flow variable, as follows:
|
||||
The `var` element declares a flow variable, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -450,13 +458,13 @@ With the default implementation, any objects stored in flash scope need to be se
|
||||
[[_scopes_conversation_scope]]
|
||||
=== Conversation Scope
|
||||
|
||||
Conversation scope gets allocated when a top-level flow starts and destroyed when the top-level flow ends.
|
||||
Conversation scope gets allocated when a top-level flow starts and gets destroyed when the top-level flow ends.
|
||||
Conversation scope is shared by a top-level flow and all of its sub-flows.
|
||||
With the default implementation, conversation-scoped objects are stored in the HTTP session and should generally be serializable to account for typical session replication.
|
||||
|
||||
=== Choosing a Scope
|
||||
|
||||
The scope to use is often determined contextually, for example depending on where a variable is defined -- at the start of the flow definition (flow scope), inside a a view state (view scope), and so on.
|
||||
The scope to use is often determined contextually -- for example, depending on where a variable is defined: at the start of the flow definition (flow scope), inside a a view state (view scope), and so on.
|
||||
In other cases (for example, in EL expressions and Java code), you must specify it explicitly.
|
||||
Subsequent sections explain how this is done.
|
||||
|
||||
@@ -468,7 +476,7 @@ The flow waits until the sub-flow returns and responds to the sub-flow outcome.
|
||||
[[_subflow_state_element]]
|
||||
=== The `subflow-state` Element
|
||||
|
||||
You can use the `subflow-state` element to call another flow as a subflow, as follows:
|
||||
The `subflow-state` element calls another flow as a subflow, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -488,7 +496,7 @@ When the flow returns with a `guestCreated` outcome, the new guest is added to t
|
||||
[[_subflow_state_element_input]]
|
||||
==== Passing a Sub-flow Input
|
||||
|
||||
You can use the `input` element to pass input to the subflow, as follows:
|
||||
The `input` element passes input to the subflow, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
|
||||
@@ -9,9 +9,9 @@ EL is used for many things within a flow, including:
|
||||
* Accessing client data, such as declaring flow inputs or referencing request parameters.
|
||||
* Accessing data in Web Flow's `RequestContext`, such as `flowScope` or `currentEvent`.
|
||||
* Invoking methods on Spring-managed objects through actions.
|
||||
* Resolving expressions, such as state transition criteria, sub-flow ids, and view names.
|
||||
* Resolving expressions, such as state transition criteria, sub-flow IDs, and view names.
|
||||
|
||||
EL is also used to bind form parameters to model objects and, reversely, to render formatted form fields from the properties of a model object.
|
||||
EL is also used to bind form parameters to model objects and, conversely, to render formatted form fields from the properties of a model object.
|
||||
That, however, does not apply when using Web Flow with JSF.
|
||||
In that case, the standard JSF component lifecyle applies.
|
||||
|
||||
@@ -61,11 +61,8 @@ The preceding expression is a template expression.
|
||||
The result of evaluation is a string that concatenates literal text such as `error-` and `.xhtml` with the result of evaluating `externalContext.locale`.
|
||||
You need explicit delimiters here to demarcate standard expression blocks within the template.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
See the Web Flow XML schema for a complete listing of those XML attributes that accept standard expressions and those that accept template expressions.
|
||||
NOTE: See the Web Flow XML schema for a complete listing of those XML attributes that accept standard expressions and those that accept template expressions.
|
||||
You can also use F2 in Eclipse (or equivalent shortcuts in other IDEs) to access available documentation when typing out specific flow definition attributes.
|
||||
====
|
||||
|
||||
[[_el_language_choices]]
|
||||
=== EL Implementations
|
||||
@@ -85,7 +82,7 @@ It is distributed as a separate jar (`org.springframework.expression`) in the Sp
|
||||
==== Unified EL
|
||||
|
||||
Use of the https://en.wikipedia.org/wiki/Unified_Expression_Language[Unified EL] also implies a dependency on `el-api`, although that is typically provided by your web container.
|
||||
Although Spring EL is the default and recommended expression language to use, you can replace it with Unified EL if you wish to do so.
|
||||
Although Spring EL is the default and recommended expression language to use, you can replace it with Unified EL.
|
||||
To do so, you need the following Spring configuration to plug in the `WebFlowELExpressionParser` to the `flow-builder-services`:
|
||||
|
||||
====
|
||||
@@ -138,12 +135,12 @@ For more information on Spring EL syntax, see the https://docs.spring.io/spring/
|
||||
[[_el_variables]]
|
||||
=== Special EL Variables
|
||||
|
||||
There are several implicit variables you may reference from within a flow.
|
||||
You can reference several implicit variables from within a flow.
|
||||
|
||||
Keep in mind this general rule:
|
||||
You should use variables that refer to data scopes (`flowScope`, `viewScope`, `requestScope`, and so on) only when you assign a new variable to one of the scopes.
|
||||
|
||||
For example, when assigning the result of the call to `bookingService.findHotels(searchCriteria)` to a new variable called `hotels`, you must prefix it with a scope variable in order to let Web Flow know where you want it stored.
|
||||
For example, when assigning the result of the call to `bookingService.findHotels(searchCriteria)` to a new variable called `hotels`, you must prefix it with a scope variable to let Web Flow know where you want it stored.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
@@ -270,7 +267,7 @@ The following listing defines a `flashScope` variable:
|
||||
You can use `conversationScope` to assign a conversation variable.
|
||||
Conversation scope gets allocated when a top-level flow starts and destroyed when the top-level flow ends.
|
||||
Conversation scope is shared by a top-level flow and all of its sub-flows.
|
||||
With the default implementation, conversation scoped objects are stored in the HTTP session and should generally be serializable to account for typical session replication.
|
||||
With the default implementation, conversation-scoped objects are stored in the HTTP session and should generally be serializable to account for typical session replication.
|
||||
The following listing defines a `conversationScope` variable:
|
||||
|
||||
====
|
||||
@@ -283,7 +280,7 @@ The following listing defines a `conversationScope` variable:
|
||||
[[_el_variable_requestparameters]]
|
||||
==== The `requestParameters` Variable
|
||||
|
||||
You can use `requestParameters` to access a client request parameter, as follows:
|
||||
The `requestParameters` variable accesses a client request parameter, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -295,7 +292,7 @@ You can use `requestParameters` to access a client request parameter, as follows
|
||||
[[_el_variable_currentevent]]
|
||||
==== The `currentEvent` Variable
|
||||
|
||||
You can use `currentEvent` to access attributes of the current `Event`, as follows:
|
||||
The `currentEvent` variable accesses attributes of the current `Event`, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -307,7 +304,7 @@ You can use `currentEvent` to access attributes of the current `Event`, as follo
|
||||
[[_el_variable_currentuser]]
|
||||
==== The `currentUser` Variable
|
||||
|
||||
You can use `currentUser` to access the authenticated `Principal`, as follows:
|
||||
The `currentUser` variable accesses the authenticated `Principal`, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -320,7 +317,7 @@ You can use `currentUser` to access the authenticated `Principal`, as follows:
|
||||
[[_el_variable_messagecontext]]
|
||||
==== The `messageContext` Variable
|
||||
|
||||
You can use `messageContext` to access a context to retrieve and create flow execution messages, including error and success messages.
|
||||
The `messageContext` variable accesses a context to retrieve and create flow execution messages, including error and success messages.
|
||||
See the `MessageContext` Javadocs for more information.
|
||||
The following example uses the `messageContext` variable:
|
||||
|
||||
@@ -334,7 +331,7 @@ The following example uses the `messageContext` variable:
|
||||
[[_el_variable_resourcebundle]]
|
||||
==== The `resourceBundle` Variable
|
||||
|
||||
You can use `resourceBundle` to access a message resource, as follows:
|
||||
The `resourceBundle` variable accesses a message resource, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -346,25 +343,25 @@ You can use `resourceBundle` to access a message resource, as follows:
|
||||
[[_el_variable_requestcontext]]
|
||||
==== The `flowRequestContext` Variable
|
||||
|
||||
You can use the `flowRequestContext` variable to access the `RequestContext` API, which is a representation of the current flow request.
|
||||
See the API Javadocs for more information.
|
||||
The `flowRequestContext` variable accesses the `RequestContext` API, which is a representation of the current flow request.
|
||||
See the https://docs.spring.io/spring-webflow/docs/current/api/org/springframework/webflow/execution/RequestContext.html[API Javadocs] for more information.
|
||||
|
||||
[[_el_variable_flowexecutioncontext]]
|
||||
==== The `flowExecutionContext` Variable
|
||||
|
||||
You can use the `flowExecutionContext` variable to access the `FlowExecutionContext` API, which is a representation of the current flow state.
|
||||
See the API Javadocs for more information.
|
||||
The `flowExecutionContext` variable accesses the `FlowExecutionContext` API, which is a representation of the current flow state.
|
||||
See the https://docs.spring.io/spring-webflow/docs/current/api/org/springframework/webflow/execution/FlowExecutionContext.html[API Javadocs] for more information.
|
||||
|
||||
[[_el_variable_flowexecutionurl]]
|
||||
==== The `flowExecutionUrl` Variable
|
||||
|
||||
You can use the `flowExecutionUrl` variable to access the context-relative URI for the current flow execution view-state.
|
||||
The `flowExecutionUrl` variable accesses the context-relative URI for the current flow execution view-state.
|
||||
|
||||
[[_el_variable_externalcontext]]
|
||||
==== The `externalContext` Variable
|
||||
|
||||
You can use the `externalContext` variable to access the client environment, including user session attributes.
|
||||
See the `ExternalContext` API JavaDocs for more information.
|
||||
The `externalContext` variable accesses the client environment, including user session attributes.
|
||||
See the `ExternalContext` https://docs.spring.io/spring-webflow/docs/current/api/org/springframework/webflow/context/ExternalContext.html[API JavaDocs] for more information.
|
||||
The following example uses the `externalContext` variable:
|
||||
|
||||
====
|
||||
|
||||
@@ -18,7 +18,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
|_action_
|
||||
|_*_
|
||||
|use <evaluate />
|
||||
|Use `<evaluate />`.
|
||||
|
||||
^| bean
|
||||
| *
|
||||
@@ -48,7 +48,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
| _argument_
|
||||
| _*_
|
||||
| Use <evaluate expression="func(arg1, arg2, ...)"/>
|
||||
| Use `<evaluate expression="func(arg1, arg2, ...)"/>`.
|
||||
|
||||
^| expression
|
||||
|
|
||||
@@ -76,11 +76,11 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
| _attribute-mapper_
|
||||
| _*_
|
||||
| input and output elements can be in flows or sub-flows directly
|
||||
| Input and output elements can be in flows or sub-flows directly.
|
||||
|
||||
^| bean
|
||||
| *
|
||||
| Now `subflow-attribute-mapper` attribute on `subflow-state`
|
||||
| Now `subflow-attribute-mapper` attribute on `subflow-state`.
|
||||
|
||||
| _bean-action_
|
||||
| _*_
|
||||
@@ -148,7 +148,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
^| name
|
||||
| *
|
||||
| Use <evaluate ...> <attribute name=`"name`" value="..." /> </evaluate>
|
||||
| Use `<evaluate ...> <attribute name=`"name`" value="..." /> </evaluate>`.
|
||||
|
||||
^| *
|
||||
| result
|
||||
@@ -160,7 +160,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
| _evaluation-result_
|
||||
| _*_
|
||||
| Use <evaluate result="..." />
|
||||
| Use `<evaluate result="..." />`.
|
||||
|
||||
^| name
|
||||
| *
|
||||
@@ -244,7 +244,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
^| scope
|
||||
| *
|
||||
| Prefix name with scope <input name="flowScope.foo" />
|
||||
| Prefix name with scope `<input name="flowScope.foo" />`.
|
||||
|
||||
^| required
|
||||
| required
|
||||
@@ -260,7 +260,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
| _input-mapper_
|
||||
| _*_
|
||||
| Inputs can be in flows and subflows directly
|
||||
| Inputs can be in flows and subflows directly.
|
||||
|
||||
| _mapping_
|
||||
| _input or output_
|
||||
@@ -268,11 +268,11 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
^| source
|
||||
| name or value
|
||||
| Name when in flow element, value when in subflow-state element
|
||||
| Name when in flow element, value when in the `subflow-state` element.
|
||||
|
||||
^| target
|
||||
| name or value
|
||||
| Value when in flow element, name when in subflow-state element
|
||||
| Value when in flow element, name when in the `subflow-state` element.
|
||||
|
||||
^| target-collection
|
||||
| *
|
||||
@@ -292,11 +292,11 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
| _method-argument_
|
||||
| _*_
|
||||
| Use <evaluate expression="func(arg1, arg2, ...)"/>
|
||||
| Use `<evaluate expression="func(arg1, arg2, ...)"/>`.
|
||||
|
||||
| _method-result_
|
||||
| _*_
|
||||
| Use <evaluate result="..." />
|
||||
| Use `<evaluate result="..." />`.
|
||||
|
||||
^| name
|
||||
| *
|
||||
@@ -316,7 +316,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
^| scope
|
||||
| *
|
||||
| Prefix name with scope <output name="flowScope.foo" />
|
||||
| Prefix name with scope `<output name="flowScope.foo" />`.
|
||||
|
||||
^| required
|
||||
| required
|
||||
@@ -332,7 +332,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
| _output-mapper_
|
||||
| _*_
|
||||
| Output can be in flows and subflows directly
|
||||
| Output can be in flows and subflows directly.
|
||||
|
||||
| _render-actions_
|
||||
| _on-render_
|
||||
@@ -348,7 +348,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
^| scope
|
||||
| *
|
||||
| Prefix name with scope <set name="flowScope.foo" />
|
||||
| Prefix name with scope `<set name="flowScope.foo" />`.
|
||||
|
||||
^| value
|
||||
| value
|
||||
@@ -356,7 +356,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
^| name
|
||||
| *
|
||||
| Use <set ...> <attribute name=`"name`" value="..." /> </set>
|
||||
| Use `<set ...> <attribute name=`"name`" value="..." /> </set>`.
|
||||
|
||||
^| *
|
||||
| type
|
||||
@@ -368,7 +368,7 @@ See the upgrade guide for more details about changes between Web Flow 1.0 and 2.
|
||||
|
||||
| _start-state_
|
||||
| _*_
|
||||
| Now <flow start-state="...">, or defaults to the first state in the flow
|
||||
| Now `<flow start-state="...">` or defaults to the first state in the flow.
|
||||
|
||||
^| idref
|
||||
| *
|
||||
|
||||
@@ -4,7 +4,7 @@ Flow inheritance lets one flow inherit the configuration of another flow.
|
||||
Inheritance can occur at both the flow and state levels.
|
||||
A common use case is for a parent flow to define global transitions and exception handlers, and then each child flow can inherit those settings.
|
||||
|
||||
In order for a parent flow to be found, it must be added to the `flow-registry` like any other flow.
|
||||
In order for a parent flow to be found, it must be added to the `flow-registry`, as any other flow.
|
||||
|
||||
[[_flow_inheritance_java_comparison]]
|
||||
=== Is Flow Inheritance Similar to Java Inheritance?
|
||||
@@ -31,20 +31,21 @@ Spring Web Flow has two types of inheritance:
|
||||
==== Flow-level Inheritance
|
||||
|
||||
Flow level inheritance is defined by the `parent` attribute on the `flow` element.
|
||||
The attribute contains a comma separated list of flow identifiers to inherit from.
|
||||
The child flow will inherit from each parent in the order it is listed adding elements and content to the resulting flow.
|
||||
The resulting flow from the first merge will be considered the child in the second merge, and so on.
|
||||
The attribute contains a comma-separated list of flow identifiers from which to inherit.
|
||||
The child flow inherits from each parent in the order it is listed, adding elements and content to the resulting flow.
|
||||
The resulting flow from the first merge is considered the child in the second merge, and so on.
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<flow parent="common-transitions, common-states">
|
||||
----
|
||||
====
|
||||
|
||||
[[_flow_inheritance_level_state]]
|
||||
=== State-level Inheritance
|
||||
|
||||
State level inheritance is similar to flow level inheritance, except only one state inherits from the parent, instead of the entire flow.
|
||||
State-level inheritance is similar to flow-level inheritance, except only one state inherits from the parent, instead of the entire flow.
|
||||
|
||||
Unlike flow inheritance, only a single parent is allowed.
|
||||
Additionally, the identifier of the flow state to inherit from must also be defined.
|
||||
@@ -83,9 +84,10 @@ If an abstract flow attempts to run, a `FlowBuilderException` is thrown.
|
||||
When a child flow inherits from its parent, the parent and child are merged together to create a new flow.
|
||||
There are rules for every element in the Web Flow definition language that govern how that particular element is merged.
|
||||
|
||||
There are two types of elements: _mergeable_ and _non-mergeable_.
|
||||
Mergeable elements always attempt to merge together if the elements are similar.
|
||||
Non-mergeable elements in a parent or child flow are always contained in the resulting flow intact.
|
||||
There are two types of elements:
|
||||
|
||||
* Mergeable: Mergeable elements always attempt to merge together if the elements are similar.
|
||||
* Non-mergeable:Non-mergeable elements in a parent or child flow are always contained in the resulting flow intact.
|
||||
They are not modified as part of the merge process.
|
||||
|
||||
NOTE: Paths to external resources in the parent flow should be absolute.
|
||||
@@ -107,8 +109,8 @@ The mergeable elements are:
|
||||
|
||||
* `action-state`: Merges on the ID
|
||||
* `attribute`: Merges on the name
|
||||
* `decision-state`: ID
|
||||
* `end-state`: ID
|
||||
* `decision-state`: Merges on the ID
|
||||
* `end-state`: Merges on the ID
|
||||
* `flow`: Always merges
|
||||
* `if`: Test
|
||||
* `on-end`: Always merges
|
||||
|
||||
@@ -39,8 +39,8 @@ To use the flow-scoped `PersistenceContext` pattern, first mark your flow as a `
|
||||
====
|
||||
|
||||
Then configure the correct `FlowExecutionListener` to apply this pattern to your flow.
|
||||
If using Hibernate, register the `HibernateFlowExecutionListener`.
|
||||
If using JPA, register the `JpaFlowExecutionListener`.
|
||||
If you use Hibernate, register the `HibernateFlowExecutionListener`.
|
||||
If you use JPA, register the `JpaFlowExecutionListener`.
|
||||
The following example uses JPA:
|
||||
|
||||
====
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
== Securing Flows
|
||||
|
||||
Security is an important concept for any application.
|
||||
End users should not be able to access any portion of a site simply by guessing the URL.
|
||||
End users should not be able to access any portion of a site by simply guessing the URL.
|
||||
Areas of a site that are sensitive must ensure that only authorized requests are processed.
|
||||
Spring Security is a proven security platform that can integrate with your application at multiple levels.
|
||||
This section focuses on securing flow execution.
|
||||
@@ -10,13 +10,13 @@ This section focuses on securing flow execution.
|
||||
[[_flow_security_how_to]]
|
||||
=== How Do I Secure a Flow?
|
||||
|
||||
Securing a flow is a three step process:
|
||||
Securing a flow is a three-step process:
|
||||
|
||||
. Configure Spring Security with authentication and authorization rules.
|
||||
. Annotate the flow definition with the secured element to define the security rules.
|
||||
. Add the `SecurityFlowExecutionListener` to process the security rules.
|
||||
|
||||
Each of these steps must be completed or flow security rules are not applied.
|
||||
Each of these steps must be completed, or flow security rules are not applied.
|
||||
|
||||
[[_flow_security_secured_element]]
|
||||
=== The `secured` Element
|
||||
@@ -27,7 +27,7 @@ This may not occur more than once per stage of the flow execution that is secure
|
||||
Three phases of a flow can be secured: flows, states, and transitions.
|
||||
In each case, the syntax for the `secured` element is identical.
|
||||
The `secured` element is located inside the element it secures.
|
||||
For example, to secure a state, the secured element occurs directly inside that state, as follows:
|
||||
For example, to secure a state, the `secured` element occurs directly inside that state, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -42,7 +42,7 @@ For example, to secure a state, the secured element occurs directly inside that
|
||||
[[_flow_security_secured_element_attributes]]
|
||||
==== Security Attributes
|
||||
|
||||
The `attributes` attribute is a comma separated list of Spring Security authorization attributes.
|
||||
The value of `attributes` is a comma separated list of Spring Security authorization attributes.
|
||||
Often, these are specific security roles.
|
||||
The attributes are compared against the user's granted attributes by a Spring Security access decision manager.
|
||||
|
||||
@@ -79,7 +79,7 @@ The `match` attribute is respected only if the default access decision manager i
|
||||
=== The `SecurityFlowExecutionListener`
|
||||
|
||||
Defining security rules in the flow by themselves does not protect the flow.
|
||||
A `SecurityFlowExecutionListener` must also be defined in the webflow configuration and applied to the flow executor, as follows:
|
||||
You must also define a `SecurityFlowExecutionListener` in the webflow configuration and apply it to the flow executor, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -166,9 +166,9 @@ The following example configures Spring Security for a web flow:
|
||||
==== `web.xml` Configuration
|
||||
|
||||
In the `web.xml` file, a `filter` is defined to intercept all requests.
|
||||
This filter listens for login/logout requests and processes them accordingly.
|
||||
It will also catch `AccesDeniedException` instances and redirect the user to the login page.
|
||||
The follwoing example defines such filters:
|
||||
This filter listens for login and logout requests and processes them accordingly.
|
||||
It also catches `AccesDeniedException` instances and redirects the user to the login page.
|
||||
The following example defines such filters:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
|
||||
@@ -6,27 +6,26 @@ It covers implementing flows in end-user applications and working with the featu
|
||||
It also covers extending the framework and the overall architectural model.
|
||||
|
||||
[[_system_requirements]]
|
||||
=== What Web Flow Requires to Run
|
||||
=== Web Flow Requirements
|
||||
|
||||
Java 1.8 or higher.
|
||||
|
||||
Spring 5.0 or higher.
|
||||
* Java 1.8 or higher.
|
||||
* Spring 5.0 or higher.
|
||||
|
||||
=== Resources
|
||||
|
||||
You can ask questions and interact on StackOverflow by using the designated tags.
|
||||
See https://spring.io/questions[Spring at StackOverflow].
|
||||
See https://stackoverflow.com/questions/tagged/spring-webflow[Spring Web Flow at StackOverflow].
|
||||
|
||||
You can report bugs and make requests by using the https://jira.spring.io[Spring Issue Tracker].
|
||||
|
||||
You can submit pull requests and work with the source code.
|
||||
See https://github.com/spring-projects/spring-webflow[Web Flow on Github].
|
||||
See https://github.com/spring-projects/spring-webflow[Spring Web Flow on Github].
|
||||
|
||||
[[_jars_mvn_central]]
|
||||
=== Accessing Web Flow artifacts from Maven Central
|
||||
=== Accessing Web Flow Artifacts from Maven Central
|
||||
|
||||
Each jar in the Web Flow distribution is available in the https://search.maven.org[Maven Central Repository].
|
||||
This lets you easily integrate Web Flow into your application if you are already using Maven as the build system for your web development project.
|
||||
This lets you easily integrate Web Flow into your application if you already use Maven as the build system for your web development project.
|
||||
|
||||
To access Web Flow jars from Maven Central, declare the following dependency in your pom:
|
||||
|
||||
@@ -42,7 +41,7 @@ To access Web Flow jars from Maven Central, declare the following dependency in
|
||||
----
|
||||
====
|
||||
|
||||
If you use JavaServer Faces, declare the following dependency in your pom (includes the `spring-binding`, `spring-webflow` transitive dependencies):
|
||||
If you use JavaServer Faces, declare the following dependency in your pom (includes the `spring-binding` and `spring-webflow` transitive dependencies):
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -59,7 +58,7 @@ If you use JavaServer Faces, declare the following dependency in your pom (inclu
|
||||
=== Accessing Nightly Builds and Milestone Releases
|
||||
|
||||
Nightly snapshots of Web Flow development branches are available by using Maven.
|
||||
These snapshot builds are useful for testing out fixes you depend on in advance of the next release and provide a convenient way for you to provide feedback about whether a fix meets your needs.
|
||||
These snapshot builds are useful for testing fixes you depend on in advance of the next release and provide a convenient way for you to provide feedback about whether a fix meets your needs.
|
||||
|
||||
==== Accessing Snapshots and Milestones with Maven
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ In the following example, we map all URLs that begin with `/spring/` to the serv
|
||||
The servlet needs to be configured.
|
||||
An `init-param` is used in the servlet to pass the `contextConfigLocation`.
|
||||
This is the location of the Spring configuration for your web application.
|
||||
The following listing shows the configuration details:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -36,13 +37,13 @@ This is the location of the Spring configuration for your web application.
|
||||
----
|
||||
====
|
||||
|
||||
In order for JSF to bootstrap correctly, the `FacesServlet` must be configured in `web.xml` as it normally would, even though you generally do not need to route requests through it at all when you use JSF with Spring Web Flow.
|
||||
For JSF to bootstrap correctly, the `FacesServlet` must be configured in `web.xml` as it normally would be, even though you generally do not need to route requests through it at all when you use JSF with Spring Web Flow.
|
||||
The following listing shows the configuration details:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<!-- Just here so the JSF implementation can initialize, *not* used at runtime -->
|
||||
<!-- Just here so the JSF implementation can initialize. *Not* used at runtime. -->
|
||||
<servlet>
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
|
||||
@@ -174,7 +175,7 @@ In a JSF environment, you also need the following Spring MVC-related configurati
|
||||
|
||||
The `resources` custom namespace element delegates JSF resource requests to the JSF resource API.
|
||||
The `JsfFlowHandlerAdapter` is a replacement for the `FlowHandlerAdapter` normally used with Web Flow.
|
||||
This adapter initializes itself with a `JsfAjaxHandler` instead of the `SpringJavaSciprtAjaxHandler`.
|
||||
This adapter initializes itself with a `JsfAjaxHandler` instead of the `SpringJavaScriptAjaxHandler`.
|
||||
|
||||
When you use Java configuration, the `AbstractFacesFlowConfiguration` base class automatically registers `JsfResourceRequestHandler`, so there is nothing further to do.
|
||||
|
||||
@@ -183,12 +184,12 @@ When you use Java configuration, the `AbstractFacesFlowConfiguration` base class
|
||||
|
||||
When you use JSF with Spring Web Flow, you can completely replace the JSF managed bean facility with a combination of Web Flow managed variables and Spring managed beans.
|
||||
It gives you a good deal more control over the lifecycle of your managed objects with well-defined hooks for initialization and execution of your domain model.
|
||||
Additionally, since you are presumably already using Spring for your business layer, it reduces the conceptual overhead of having to maintain two different managed bean models.
|
||||
Additionally, since you presumably already use Spring for your business layer, it reduces the conceptual overhead of having to maintain two different managed bean models.
|
||||
|
||||
If you are doing pure JSF development, you may quickly find that request scope is not long-lived enough for storing conversational model objects that drive complex event-driven views.
|
||||
In JSF, the usual option is to begin putting things into session scope, with the extra burden of needing to clean the objects up before progressing to another view or functional area of the application.
|
||||
If you do pure JSF development, you may quickly find that request scope is not long-lived enough for storing conversational model objects that drive complex event-driven views.
|
||||
In JSF, the usual option is to begin putting things into session scope, with the extra burden of needing to clean up the objects before progressing to another view or functional area of the application.
|
||||
What is really needed is a managed scope that is somewhere between request and session scope.
|
||||
JSF provides flash and view scopes that can be accessed programmatically through UIViewRoot.getViewMap().
|
||||
JSF provides flash and view scopes that can be accessed programmatically through `UIViewRoot.getViewMap()`.
|
||||
Spring Web Flow provides access to flash, view, flow, and conversation scopes.
|
||||
These scopes are seamlessly integrated through JSF variable resolvers and work the same in all JSF applications.
|
||||
|
||||
@@ -234,7 +235,7 @@ To define a view instance variable, you can use the `var` element inside a `view
|
||||
[[_spring_faces_spring_beans]]
|
||||
==== Using Scoped Spring Beans
|
||||
|
||||
Though defining autowired flow instance variables provides nice modularization and readability, occasions may arise where you want to utilize the other capabilities of the Spring container, such as Aspect-oriented Programming (AOP).
|
||||
Though defining autowired flow instance variables provides nice modularization and readability, occasions may arise where you want to use the other capabilities of the Spring container, such as Aspect-oriented Programming (AOP).
|
||||
In these cases, you can define a bean in your Spring `ApplicationContext` and give it a specific web flow scope, as follows:
|
||||
|
||||
====
|
||||
@@ -306,7 +307,7 @@ For example, on postback from a view where the action event was fired by a compo
|
||||
|
||||
Spring Web Flow provides two custom DataModel types: `OneSelectionTrackingListDataModel` and `ManySelectionTrackingListDataModel`.
|
||||
As the names indicate, they keep track of one or multiple selected rows.
|
||||
This is done with the help of a `SelectionTrackingActionListener` listener, which responds to JSF action events and invokes the appropriate methods on the `SelectinAware` data models to record the currently clicked row.
|
||||
This is done with the help of a `SelectionTrackingActionListener` listener, which responds to JSF action events and invokes the appropriate methods on the `SelectionAware` data models to record the currently clicked row.
|
||||
|
||||
To understand how this is configured, keep in mind that the `FacesConversionService` registers a `DataModelConverter` against the alias `dataModel` on startup.
|
||||
When `result-type="dataModel"` is used in a flow definition, it causes the `DataModelConverter` to be used.
|
||||
@@ -343,7 +344,7 @@ The initial `view-state` definition to load and display the list would be as fol
|
||||
----
|
||||
====
|
||||
|
||||
You can construct a JSF DataTable that displays the current `hotels` list and then place a "`More Results`" link below the table, as follows:
|
||||
You can construct a JSF DataTable that displays the current `hotels` list and then place a `More Results` link below the table, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -352,7 +353,7 @@ You can construct a JSF DataTable that displays the current `hotels` list and th
|
||||
----
|
||||
====
|
||||
|
||||
This `commandLink` signals a "`next`" event from its `action` attribute.
|
||||
This `commandLink` signals a `next` event from its `action` attribute.
|
||||
You can then handle the event by adding to the `view-state` definition, as follows:
|
||||
|
||||
====
|
||||
@@ -380,7 +381,7 @@ The same view is re-rendered, since there was no `to` attribute on the `transiti
|
||||
The next logical level beyond in-page events are events that require navigation to another view, with some manipulation of the model along the way.
|
||||
Achieving this with pure JSF would require adding a navigation rule to `faces-config.xml` and likely some intermediary Java code in a JSF managed bean (both tasks requiring a re-deploy). With the flow definition language, you can handle such a case concisely in one place in a way similar to how in-page events are handled.
|
||||
|
||||
Continuing on with our use case of manipulating a paged list of results, suppose we want each row in the displayed `DataTable` to contain a link to a detail page for that row instance.
|
||||
Continuing with our use case of manipulating a paged list of results, suppose we want each row in the displayed `DataTable` to contain a link to a detail page for that row instance.
|
||||
You can add a column to the table containing the following `commandLink` component, as follows:
|
||||
|
||||
====
|
||||
@@ -410,7 +411,7 @@ This raises the `select` event, which you can then handle by adding another `tra
|
||||
----
|
||||
====
|
||||
|
||||
Here, the `select` event is handled by pushing the currently selected hotel instance from the `DataTable` into flow scope so that it may be referenced by the "reviewHotel" `view-state` .
|
||||
Here, the `select` event is handled by pushing the currently selected hotel instance from the `DataTable` into flow scope so that it may be referenced by the `reviewHotel` `view-state` .
|
||||
|
||||
[[_spring_faces_model_validation]]
|
||||
==== Performing Model Validation
|
||||
@@ -419,9 +420,9 @@ JSF provides useful facilities for validating input at field-level before change
|
||||
However, when you need to then perform more complex validation at the model-level after the updates have been applied, you are generally left with having to add more custom code to your JSF action methods in the managed bean.
|
||||
Validation of this sort is something that is generally a responsibility of the domain model itself, but it is difficult to get any error messages propagated back to the view without introducing an undesirable dependency on the JSF API in your domain layer.
|
||||
|
||||
With Web Flow, you can utilize the generic and low-level `MessageContext` in your business code, and any messages added there are then available to the `FacesContext` at render time.
|
||||
With Web Flow, you can use the generic and low-level `MessageContext` in your business code, and any messages added there are then available to the `FacesContext` at render time.
|
||||
|
||||
For example, suppose you have a view where the user enters the necessary details to complete a hotel booking, and you need to ensure the "`Check In`" and "`Check Out`" dates adhere to a given set of business rules.
|
||||
For example, suppose you have a view where the user enters the necessary details to complete a hotel booking, and you need to ensure the `Check In` and `Check Out` dates adhere to a given set of business rules.
|
||||
You can invoke such model-level validation from a `transition` element, as follows:
|
||||
|
||||
====
|
||||
@@ -465,12 +466,12 @@ In Spring Web Flow, you also have the option to specify the IDs to use for parti
|
||||
[[_spring_faces_embedded_mode]]
|
||||
=== Embedding a Flow On a Page
|
||||
|
||||
By default, when a flow enters a view state, it executes a client-side redirect before rendering the view.
|
||||
By default, when a flow enters a view state, it runs a client-side redirect before rendering the view.
|
||||
This approach is known as "`POST-REDIRECT-GET`".
|
||||
It has the advantage of separating the form processing for one view from the rendering of the next view.
|
||||
As a result, the browser "`Back`" and "`Refresh`" buttons work seamlessly without causing any browser warnings.
|
||||
As a result, the browser Back and Refresh buttons work seamlessly without causing any browser warnings.
|
||||
|
||||
Normally the client-side redirect is transparent from a user's perspective.
|
||||
Normally, the client-side redirect is transparent from a user's perspective.
|
||||
However, there are situations where "`POST-REDIRECT-GET`" may not bring the same benefits.
|
||||
For example, it may sometimes be useful to embed a flow on a page and drive it with Ajax requests, to refresh only the area of the page where the flow is rendered.
|
||||
Not only is it unnecessary to use client-side redirects in this case, it is also not the desired behavior with regards to keeping the surrounding content of the page intact.
|
||||
@@ -489,28 +490,27 @@ To indicate a flow should execute in "`page embedded`" mode, you can pass an ext
|
||||
When launched in "`page embedded`" mode, the sub-flow does not issue flow execution redirects during Ajax requests.
|
||||
|
||||
For examples of an embedded flow, see the `webflow-primefaces-showcase` project.
|
||||
You can check out the source code locally, build it as you would a Maven project, and import it into Eclipse, as follows:
|
||||
You can check out the source code locally, build it as you would a Maven project, and import it into Eclipse or another IDE, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
cd some-directory
|
||||
svn co https://src.springframework.org/svn/spring-samples/webflow-primefaces-showcase
|
||||
cd webflow-primefaces-showcase
|
||||
git clone https://github.com/spring-projects/spring-webflow-samples.git
|
||||
cd primefaces-showcase
|
||||
mvn package
|
||||
# import into Eclipse
|
||||
----
|
||||
====
|
||||
//TODO The URL and `svn` need to be updated.
|
||||
|
||||
The specific example you need to look at is under the "`Advanced Ajax`" tab and is called "`Top Flow with Embedded Sub-Flow`".
|
||||
|
||||
[[_spring_faces_redirect_in_same_state]]
|
||||
=== Redirect In the Same State
|
||||
|
||||
By default Web Flow does a client-side redirect even it it remains in the same view state, as long as the current request is not an Ajax request.
|
||||
By default, Web Flow does a client-side redirect even it it remains in the same view state, as long as the current request is not an Ajax request.
|
||||
This is quite useful after form validation failures (for example).
|
||||
If the user hits "`Refresh`" or "`Back`", they do not see any browser warnings.
|
||||
If the user hits Refresh or Back, they do not see any browser warnings.
|
||||
They would if the Web Flow did not do a redirect.
|
||||
|
||||
This can lead to a problem specific to JSF environments where a specific Sun Mojarra listener component caches the `FacesContext`, assuming the same instance is available throughout the JSF lifecycle.
|
||||
@@ -534,8 +534,8 @@ However, if you experience this issue, you can disable client-side redirects wit
|
||||
[[_spring_faces_file_upload]]
|
||||
=== Handling File Uploads with JSF
|
||||
|
||||
Most JSF component providers include some form of 'file upload' component.
|
||||
Generally when working with these components JSF must take complete control of parsing multi-part requests and Spring MVC's `MultipartResolver` cannot be used.
|
||||
Most JSF component providers include some form of file upload component.
|
||||
Generally, when working with these components, JSF must take complete control of parsing multi-part requests and Spring MVC's `MultipartResolver` cannot be used.
|
||||
|
||||
Spring Web Flow has been tested with file upload components from PrimeFaces.
|
||||
Check the documentation of your JSF component library for other providers to see how to configure file upload.
|
||||
@@ -572,7 +572,7 @@ For more details, see the https://primefaces.org/documentation.html[PrimeFaces d
|
||||
|
||||
To use the library, you need to create a `taglib.xml` file and register it in `web.xml`.
|
||||
|
||||
You need to create the file `/WEB-INF/springsecurity.taglib.xml` with the following content:
|
||||
You need to create a file called `/WEB-INF/springsecurity.taglib.xml` with the following content:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -684,4 +684,4 @@ You can also use one of several EL functions in the rendered or other attribute
|
||||
The Spring Web Flow JSF integration strives to be compatible with any third-party JSF component library.
|
||||
By honoring all of the standard semantics of the JSF specification within the SWF-driven JSF lifecycle, third-party libraries in general should "`just work`". The main thing to remember is that configuration in `web.xml` changes slightly, since Web Flow requests are not routed through the standard `FacesServlet`.
|
||||
Typically, anything that is traditionally mapped to the `FacesServlet` should be mapped to the Spring `DispatcherServlet` instead.
|
||||
(You can also map to both if, for example, you are migrating a legacy JSF application page-by-page.)
|
||||
(You can also map to both if, for example, you need to migrate a legacy JSF application page-by-page.)
|
||||
|
||||
@@ -11,7 +11,7 @@ Use of the Spring JS API is demonstrated in the https://github.com/spring-projec
|
||||
|
||||
The Spring Framework provides a mechanism for serving static resources.
|
||||
See the https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-config-static-resources[Spring Framework documentation]).
|
||||
With the new `<mvc:resources>` element, resource requests (.js, .css, and others) are handled by the `DispatcherSevlet`.
|
||||
With the new `<mvc:resources>` element, resource requests (`.js`, `.css`, and others) are handled by the `DispatcherSevlet`.
|
||||
The following example shows how to configure the module in XML (Java configuration is also available):
|
||||
|
||||
====
|
||||
@@ -34,9 +34,9 @@ The following example shows how to configure the module in XML (Java configurati
|
||||
----
|
||||
====
|
||||
|
||||
This incoming maps requests for `/resources` to resources found under `/META-INF/web-resources` on the classpath.
|
||||
This maps incoming requests for `/resources` to resources found under `/META-INF/web-resources` on the classpath.
|
||||
That is where Spring JavaScript resources are bundled.
|
||||
However, you can modify the location attribute in the preceding configuration in order to serve resources from any classpath or web application relative location.
|
||||
However, you can modify the location attribute in the preceding configuration to serve resources from any location relative to the classpath or web application.
|
||||
|
||||
Note that the full resource URL depends on how your `DispatcherServlet` is mapped.
|
||||
In the `mvc-booking` sample, we have chosen to map it with the default servlet mapping (`/`), as follows:
|
||||
@@ -135,7 +135,7 @@ This approach lets you use a common decoration model to integrate any widget fro
|
||||
See the `booking-mvc` reference application for more examples of applying decorations to do things from suggestions to client-side validation.
|
||||
|
||||
When using the `ElementDecoration` to apply widgets that have rich validation behavior, a common need is to prevent the form from being submitted to the server until validation passes.
|
||||
This can be done with the `ValidateAllDecoration`, as follows:
|
||||
This can be done with `ValidateAllDecoration`, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -226,13 +226,13 @@ Thus, no special knowledge of an Ajax request is needed directly in the code, an
|
||||
==== Providing a Library-Specific `AjaxHandler`
|
||||
|
||||
The key interface for integrating various Ajax libraries with the Ajax-aware behavior of Web Flow (such as not redirecting for a partial page update) is `org.springframework.js.AjaxHandler`.
|
||||
By default, a `SpringJavascriptAjaxHandler` is configured that is able to detect an Ajax request submitted through the Spring JS client-side API and can respond appropriately in the case where a redirect is required.
|
||||
By default, a `SpringJavascriptAjaxHandler` is configured. It can detect an Ajax request submitted through the Spring JS client-side API and can respond appropriately when a redirect is required.
|
||||
To integrate a different Ajax library (be it a pure JavaScript library or a higher-level abstraction, such as an Ajax-capable JSF component library), you can inject a custom `AjaxHandler` into the `FlowHandlerAdapter` or `FlowController`.
|
||||
|
||||
[[_spring_js_ajax_mvc]]
|
||||
==== Handling Ajax Requests with Spring MVC Controllers
|
||||
|
||||
To handle Ajax requests with Spring MVC controllers, you need to configure the provided Spring MVC extensions in your Spring application context for rendering the partial response (note that these extensions require the use of Tiles for templating), as follows:
|
||||
To handle Ajax requests with Spring MVC controllers, you need to configure the provided Spring MVC extensions in your Spring application context for rendering the partial response (note that these extensions require the use of tiles for templating), as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -245,8 +245,8 @@ To handle Ajax requests with Spring MVC controllers, you need to configure the p
|
||||
|
||||
This configures the `AjaxUrlBasedViewResolver`, which, in turn, interprets Ajax requests and creates `FlowAjaxTilesView` objects to handle rendering of the appropriate fragments.
|
||||
Note that `FlowAjaxTilesView` is capable of handling the rendering for both Web Flow and pure Spring MVC requests.
|
||||
The fragments correspond to individual attributes of a Tiles view definition.
|
||||
For example, consider the following Tiles view definition:
|
||||
The fragments correspond to individual attributes of a tiles view definition.
|
||||
For example, consider the following tiles view definition:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -267,9 +267,9 @@ An Ajax request could specify the `body`, `hotelSearchForm` or `bookingsTable` t
|
||||
[[_spring_js_ajax_mvc_webflow]]
|
||||
==== Handling Ajax Requests with Spring MVC and Spring Web Flow
|
||||
|
||||
Spring Web Flow handles the optional rendering of fragments directly in the flow definition language through use of the `render` element.
|
||||
Spring Web Flow handles the optional rendering of fragments directly in the flow definition language through the use of the `render` element.
|
||||
The benefit of this approach is that the selection of fragments is completely decoupled from client-side code, such that no special parameters need to be passed with the request the way they currently must be with the pure Spring MVC controller approach.
|
||||
For example, if you wanted to render the `hotelSearchForm` fragment from the previous example Tiles view into a rich Javascript popup, you could define the following `view-state`:
|
||||
For example, if you wanted to render the `hotelSearchForm` fragment from the previous example tiles view into a rich Javascript popup, you could define the following `view-state`:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
|
||||
@@ -86,19 +86,19 @@ The adapter employs a number of defaults related to starting and resuming flow e
|
||||
* When a flow execution ends without sending a final response, the default handler tries to start a new execution in the same request.
|
||||
* Unhandled exceptions are propagated to the `Dispatcher`, unless the exception is a `NoSuchFlowExecutionException`. The default handler tries to recover from a `NoSuchFlowExecutionException` by starting over with a new execution.
|
||||
|
||||
See the API documentation for `FlowHandlerAdapter` for more information.
|
||||
See the https://docs.spring.io/spring-webflow/docs/current/api/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.html[API documentation for `FlowHandlerAdapter`] for more information.
|
||||
You may override these defaults by subclassing or by implementing your own `FlowHandler`, as discussed in the next section.
|
||||
|
||||
[[_spring_mvc_config_flow_handlers]]
|
||||
=== Implementing custom FlowHandlers
|
||||
=== Implementing Custom Flow Handlers
|
||||
|
||||
`FlowHandler` is the extension point that can be used to customize how flows are executed in a HTTP servlet environment.
|
||||
`FlowHandler` is the extension point that can be used to customize how flows are used in a HTTP servlet environment.
|
||||
A `FlowHandler` is used by the `FlowHandlerAdapter` and is responsible for:
|
||||
|
||||
* Returning the `id` of a flow definition to execute
|
||||
* Creating the input to pass new executions of that flow as they are started
|
||||
* Handling outcomes returned by executions of that flow as they end
|
||||
* Handling any exceptions thrown by executions of that flow as they occur
|
||||
* Returning the `id` of a flow definition to invoke
|
||||
* Creating the input to pass new invocations of that flow as they are started
|
||||
* Handling outcomes returned by invocations of that flow as they end
|
||||
* Handling any exceptions thrown by invocations of that flow as they occur
|
||||
|
||||
These responsibilities are illustrated in the definition of the `org.springframework.mvc.servlet.FlowHandler` interface:
|
||||
|
||||
@@ -125,7 +125,7 @@ All these operations are optional. If you do not implement them, the defaults ap
|
||||
You need only override the methods that you need.
|
||||
Specifically, you should:
|
||||
|
||||
* Override `getFlowId(HttpServletRequest)` when the ID of your flow cannot be directly derived from the HTTP request. By default, the ID of the flow to execute is derived from the `pathInfo` portion of the request URI. For example, `http://localhost/app/hotels/booking?hotelId=1` results in a flow ID of `hotels/booking` by default.
|
||||
* Override `getFlowId(HttpServletRequest)` when the ID of your flow cannot be directly derived from the HTTP request. By default, the ID of the flow to invoke is derived from the `pathInfo` portion of the request URI. For example, `http://localhost/app/hotels/booking?hotelId=1` results in a flow ID of `hotels/booking` by default.
|
||||
* Override `createExecutionInputMap(HttpServletRequest)` when you need fine-grained control over extracting flow input parameters from the `HttpServletRequest`. By default, all request parameters are treated as flow input parameters.
|
||||
* Override `handleExecutionOutcome` when you need to handle specific flow execution outcomes in a custom manner. The default behavior sends a redirect to the ended flow's URL to restart a new execution of the flow.
|
||||
* Override `handleException` when you need fine-grained control over unhandled flow exceptions. The default behavior attempts to restart the flow when a client attempts to access an ended or expired flow execution. Any other exception is re-thrown to the Spring MVC `ExceptionResolver` infrastructure by default.
|
||||
@@ -134,7 +134,7 @@ Specifically, you should:
|
||||
==== Example `FlowHandler`
|
||||
|
||||
A common interaction pattern between Spring MVC and Web Flow is for a flow to redirect to a `@Controller` when it ends.
|
||||
FlowHandler instances let this be done without coupling the flow definition itself with a specific controller URL.
|
||||
`FlowHandler` instances let this be done without coupling the flow definition itself with a specific controller URL.
|
||||
The following example `FlowHandler` redirects to a Spring MVC Controller:
|
||||
|
||||
====
|
||||
@@ -153,7 +153,7 @@ public class BookingFlowHandler extends AbstractFlowHandler {
|
||||
----
|
||||
====
|
||||
|
||||
Since this handler needs only to handle flow execution outcomes in a custom manner, nothing else is overridden.
|
||||
Since this handler needs only to handle flow invocation outcomes in a custom manner, nothing else is overridden.
|
||||
The `bookingConfirmed` outcome results in a redirect to show the new booking.
|
||||
Any other outcome redirects back to the hotel's index page.
|
||||
|
||||
@@ -188,7 +188,7 @@ The explicit redirect prefixes supported are:
|
||||
* `servletRelative:`: Redirect to a resource relative to the current servlet
|
||||
* `contextRelative:`: Redirect to a resource relative to the current web application context path
|
||||
* `serverRelative:`: Redirect to a resource relative to the server root
|
||||
* `http://` or `https://`: Redirect to a fully-qualified resource URI
|
||||
* `http://` or `https://`: Redirect to a fully qualified resource URI
|
||||
|
||||
These same redirect prefixes are also supported within a flow definition when you use the `externalRedirect:` directive in conjunction with a `view-state` or an `end-state` -- for example, `view="externalRedirect:https://springframework.org"`.
|
||||
|
||||
@@ -196,7 +196,7 @@ These same redirect prefixes are also supported within a flow definition when yo
|
||||
=== View Resolution
|
||||
|
||||
Unless otherwise specified, Web Flow maps selected view identifiers to files located within the flow's working directory.
|
||||
For existing Spring MVC and Web Flow applications, an external `ViewResolver` is likely already handling this mapping for you.
|
||||
For existing Spring MVC and Web Flow applications, an external `ViewResolver` is likely already handling this mapping for you.
|
||||
Therefore, to continue using that resolver and to avoid having to change how your existing flow views are packaged, you can configure Web Flow as follows:
|
||||
|
||||
====
|
||||
@@ -216,9 +216,9 @@ Therefore, to continue using that resolver and to avoid having to change how you
|
||||
|
||||
`MvcViewFactoryCreator` is the factory that lets you configure how the Spring MVC view system is used inside Spring Web Flow.
|
||||
You can use it to configure existing `ViewResolver` instances as well as other services, such as a custom `MessageCodesResolver`.
|
||||
You may also let data binding use Spring MVC's native BeanWrapper by setting the `useSpringBinding` flag to `true`.
|
||||
You may also let data binding use Spring MVC's native `BeanWrapper` by setting the `useSpringBinding` flag to `true`.
|
||||
This is an alternative to using the Unified EL for view-to-model data binding.
|
||||
See the JavaDoc API of this class for more information.
|
||||
See the https://docs.spring.io/spring-webflow/docs/current/api/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.html[JavaDoc API of this class] for more information.
|
||||
|
||||
[[_spring_mvc_resuming_on_event]]
|
||||
=== Signaling an Event from a View
|
||||
@@ -258,8 +258,8 @@ The following example shows a form that signals the `proceed` event when submitt
|
||||
----
|
||||
====
|
||||
|
||||
Here, Web Flow simply detects the special `\_eventId` parameter and uses its value as the event ID.
|
||||
This style should only be considered when there is one event that can be signaled on the form.
|
||||
Here, Web Flow detects the special `\_eventId` parameter and uses its value as the event ID.
|
||||
This style should be considered only when there is one event that can be signaled on the form.
|
||||
|
||||
[[_webflow_event_link]]
|
||||
==== Using a HTML Link to Signal an Event
|
||||
@@ -278,10 +278,10 @@ On the server-side, the flow handles decoding the event from within its current
|
||||
How this decoding process works is specific to the view implementation.
|
||||
Recall that a Spring MVC view implementation looks for a request parameter named ``\_eventId``.
|
||||
If no `\_eventId` parameter is found, the view looks for a parameter that starts with `\_eventId_` and uses the remaining substring as the event ID.
|
||||
If neither cases exist, no flow event is triggered.
|
||||
If neither case exists, no flow event is triggered.
|
||||
|
||||
[[_spring_mvc_embedded_flow]]
|
||||
=== Embedding A Flow On A Page
|
||||
=== Embedding a Flow on a Page
|
||||
|
||||
By default, when a flow enters a view state, it performs a client-side redirect before rendering the view.
|
||||
This approach is known as `POST-REDIRECT-GET`.
|
||||
@@ -309,28 +309,27 @@ The `mode=embedded` parameter needs to be passed only when launching the flow.
|
||||
Your only other concern is to use Ajax requests and to render only the content required to update the portion of the page displaying the flow.
|
||||
|
||||
[[_spring_mvc_embedded_flow_alternatives]]
|
||||
==== Embedded Mode Vs Default Redirect Behavior
|
||||
==== Embedded Mode Versus Default Redirect Behavior
|
||||
|
||||
By default, Web Flow does a client-side redirect upon entering every view state.
|
||||
However, if you remain in the same view state (for example, a transition without a `to` attribute), during an Ajax request, there is no client-side redirect.
|
||||
This behavior should be quite familiar to Spring Web Flow users.
|
||||
However, if you remain in the same view state (for example, a transition without a `to` attribute) during an Ajax request, there is no client-side redirect.
|
||||
It is appropriate for a top-level flow that supports the browser back button while still taking advantage of Ajax and partial rendering for use cases where you remain in the same view such as form validation, paging trough search results, and others.
|
||||
However transitions to a new view state are always followed with a client-side redirect.
|
||||
However, transitions to a new view state are always followed with a client-side redirect.
|
||||
That makes it impossible to embed a flow on a page or within a modal dialog and execute more than one view state without causing a full-page refresh.
|
||||
Hence, if your use case requires embedding a flow, you can launch it in "`embedded`" mode.
|
||||
|
||||
[[_spring_mvc_embedded_flow_examples]]
|
||||
==== Embedded Flow Examples
|
||||
|
||||
For examples of a flow embedded on a page and within a modal dialog, see to the webflow-showcase project.
|
||||
For examples of a flow embedded on a page and within a modal dialog, see the `webflow-showcase` project.
|
||||
You can check out the source code locally, build it as you would a Maven project, and import it into Eclipse, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
cd some-directory
|
||||
svn co https://src.springframework.org/svn/spring-samples/webflow-showcase
|
||||
cd webflow-showcase
|
||||
git clone https://github.com/spring-projects/spring-webflow-samples.git
|
||||
cd spring-webflow-samples/webflow-showcase
|
||||
mvn package
|
||||
# import into Eclipse
|
||||
----
|
||||
@@ -339,7 +338,7 @@ mvn package
|
||||
[[_spring_mvc_flash_output]]
|
||||
=== Saving Flow Output to MVC Flash Scope
|
||||
|
||||
You can automatically save Flow output to MVC flash scope when an `end-state` performs an internal redirect.
|
||||
You can automatically save flow output to MVC flash scope when an `end-state` performs an internal redirect.
|
||||
This is particularly useful when displaying a summary screen at the end of a flow.
|
||||
For backwards compatibility, this feature is disabled by default.
|
||||
To enable it, set `saveOutputToFlashScopeOnRedirect` on your `FlowHandlerAdapter` to `true`, as follows:
|
||||
|
||||
@@ -7,7 +7,7 @@ This chapter shows you how to set up the Web Flow system for use in any web envi
|
||||
|
||||
Web Flow provides dedicated configuration support for both Java- and XML-based configuration.
|
||||
|
||||
To get started with XML based configuration, declare the webflow config XML namespace, as follows:
|
||||
To get started with XML based configuration, declare the `webflow` config XML namespace, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -81,16 +81,19 @@ public FlowDefinitionRegistry flowRegistry() {
|
||||
[[_basic_setup_flow_executor]]
|
||||
==== Deploying a `FlowExecutor`
|
||||
|
||||
You can deploy a FlowExecutor, the central service for executing flows in XML, as follows:
|
||||
You can deploy a `FlowExecutor`, the central service for executing flows in XML, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<webflow:flow-executor id="flowExecutor" />
|
||||
----
|
||||
====
|
||||
|
||||
Deploy a FlowExecutor, the central service for executing flows in Java:
|
||||
You can deploy a `FlowExecutor`, the central service for executing flows in Java:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
|
||||
@@ -99,6 +102,7 @@ public FlowExecutor flowExecutor() {
|
||||
return getFlowExecutorBuilder(flowRegistry()).build();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
See the <<_spring_mvc>> and <<_spring_faces>> sections of this guide on how to integrate the Web Flow system with the MVC and JSF environment, respectively.
|
||||
|
||||
@@ -138,7 +142,7 @@ return getFlowDefinitionRegistryBuilder()
|
||||
|
||||
You can specify an ID to assign a custom registry identifier to a flow.
|
||||
|
||||
The following example show how to assign custom flow identifiers in XML:
|
||||
The following example shows how to assign custom flow identifiers in XML:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -248,7 +252,7 @@ With a base path defined, the algorithm that assigns flow identifiers changes sl
|
||||
Flows are now assigned registry identifiers equal to the the path segment between their base path and their file name.
|
||||
For example, if a flow definition is located at `/WEB-INF/hotels/booking/booking-flow.xml` and the base path is `/WEB-INF`, the remaining path to this flow is `hotels/booking`, which becomes the flow ID.
|
||||
|
||||
.Directory per flow definition
|
||||
.A directory for each flow definition
|
||||
TIP: It is a best practice to package each flow definition in a unique directory.
|
||||
This improves modularity, letting dependent resources be packaged with the flow definition.
|
||||
It also prevents two flows from having the same identifiers when using the convention.
|
||||
@@ -441,9 +445,9 @@ See <<_view_type_conversion>> for important information on how to provide custom
|
||||
[[_builder_service_expression_parser]]
|
||||
===== Using the Expression Parser
|
||||
|
||||
You can use the `expression-parser` attribute (in XML) or the ExpressionParser interface (in Java) to customize the `ExpressionParser` used by the Web Flow system.
|
||||
The default `ExpressionParser` uses the Unified EL if available on the classpath.
|
||||
Otherwise, it uses Spring EL.
|
||||
You can use the `expression-parser` attribute (in XML) or the `ExpressionParser` interface (in Java) to customize the `ExpressionParser` used by the Web Flow system.
|
||||
The default `ExpressionParser` uses the Unified Expression Language if available on the classpath.
|
||||
Otherwise, it uses the Spring Expression Language.
|
||||
|
||||
[[_builder_service_view_factory_creator]]
|
||||
===== Using the View Factory Creator
|
||||
@@ -461,7 +465,7 @@ When you create a flow builder services object, you can turn on development mode
|
||||
Development mode switches on hot-reloading of flow definition changes, including changes to dependent flow resources such as message bundles.
|
||||
|
||||
To turn on development mode in XML, set the `development` attribute on the `flow-builder-services` element to `true`.
|
||||
To turn on development mode in XML, use `setDevelopment(true)` on the `FlowBuilderServices` object.
|
||||
To turn on development mode in Java, use `setDevelopment(true)` on the `FlowBuilderServices` object.
|
||||
|
||||
[[_flow_executor]]
|
||||
=== Setting Flow Executor options
|
||||
@@ -573,5 +577,5 @@ To disable snapshotting, set this value to 0.
|
||||
To enable an unlimited number of snapshots, set this value to -1.
|
||||
|
||||
NOTE: History snapshots enable browser back button support.
|
||||
When snapshotting is disabled, pressing the browser back button will not work.
|
||||
When snapshotting is disabled, pressing the browser back button does not work.
|
||||
Doing so results in using an execution key that points to a snapshot that has not been recorded.
|
||||
|
||||
@@ -64,7 +64,7 @@ protected FlowDefinitionResource[] getModelResources(FlowDefinitionResourceFacto
|
||||
[[_testing_flowstartup]]
|
||||
=== Testing Flow Startup
|
||||
|
||||
The following exampel shows how to have your first test exercise the startup of your flow:
|
||||
The following example shows how to have your first test exercise the startup of your flow:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
@@ -91,8 +91,8 @@ Assertions generally verify that the flow is in the state you expect.
|
||||
=== Testing Flow Event Handling
|
||||
|
||||
You can define additional tests to exercise flow event-handling behavior.
|
||||
You goal should be to exercise all paths through the flow.
|
||||
You can use the convenient `setCurrentState(String)` method to jump to the flow state where you wish to begin your test, as follows
|
||||
Your goal should be to exercise all paths through the flow.
|
||||
You can use the convenient `setCurrentState(String)` method to jump to the flow state where you wish to begin your test, as follows:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
|
||||
@@ -6,7 +6,7 @@ This chapter shows you how to use the `view-state` element to render views withi
|
||||
[[_view_convention]]
|
||||
=== Defining View States
|
||||
|
||||
You can use the `view-state` element to define a step of the flow that renders a view and waits for a user event to resume, as follows:
|
||||
The `view-state` element defines a step of the flow that renders a view and waits for a user event to resume, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -44,7 +44,7 @@ The view ID may be a relative path to view resource in the flow's working direct
|
||||
[[_view_explicit_absolute]]
|
||||
==== Absolute View IDs
|
||||
|
||||
The view id may be a absolute path to a view resource in the webapp root directory, as follows:
|
||||
The view ID may be a absolute path to a view resource in the webapp root directory, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -133,7 +133,7 @@ The following example pages through a search results list:
|
||||
[[_view_on_render]]
|
||||
=== Running Render Actions
|
||||
|
||||
Use the `on-render` element to run one or more actions before view rendering.
|
||||
The `on-render` element runs one or more actions before view rendering.
|
||||
Render actions are run on the initial render as well as on any subsequent refreshes, including any partial re-renderings of the view.
|
||||
The following listing defines an `on-render` element:
|
||||
|
||||
@@ -149,11 +149,11 @@ The following listing defines an `on-render` element:
|
||||
[[_view_model]]
|
||||
=== Binding to a Model
|
||||
|
||||
You can use the `model` attribute to declare to which a model object the view binds.
|
||||
You can use the `model` attribute to declare a model to which object the view binds.
|
||||
This attribute is typically used in conjunction with views that render data controls, such as forms.
|
||||
It enables form data binding and validation behaviors to be driven from metadata on your model object.
|
||||
It lets form data binding and validation behaviors to be driven from metadata on your model object.
|
||||
|
||||
The following example declares an `enterBookingDetails` state manipulates the `booking` model:
|
||||
The following example declares an `enterBookingDetails` state that manipulates the `booking` model:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -162,13 +162,13 @@ The following example declares an `enterBookingDetails` state manipulates the `b
|
||||
----
|
||||
====
|
||||
|
||||
The model may be an object in any accessible scope, such as `flowScope` or ``viewScope``.
|
||||
The model may be an object in any accessible scope, such as `flowScope` or `viewScope`.
|
||||
Specifying a `model` triggers the following behavior when a view event occurs:
|
||||
|
||||
. View-to-model binding. On view postback, user input values are bound to model object properties for you.
|
||||
. Model validation. After binding, if the model object requires validation, that validation logic is invoked.
|
||||
|
||||
For a flow event to be generated that can drive a view state transition, model binding must successfully complete.
|
||||
For a flow event that can drive a view state transition to be generated, model binding must successfully complete.
|
||||
If model binding fails, the view is re-rendered to let the user revise their edits.
|
||||
|
||||
[[_view_type_conversion]]
|
||||
@@ -176,23 +176,23 @@ If model binding fails, the view is re-rendered to let the user revise their edi
|
||||
|
||||
When request parameters are used to populate the model (commonly referred to as data binding), type conversion is required to parse string-based request parameter values before setting target model properties.
|
||||
Default type conversion is available for many common Java types such as numbers, primitives, enums, and Dates.
|
||||
Users also have the ability to register their own type conversion logic for user-defined types and to override the default converters.
|
||||
Users can also register their own type conversion logic for user-defined types and to override the default converters.
|
||||
|
||||
[[_converter_options]]
|
||||
==== Type Conversion Options
|
||||
|
||||
Starting with version 2.1, Spring Web Flow uses the https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation[type conversion] and https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#format[formatting] system for nearly all type conversion needs.
|
||||
Previously, Web Flow applications used a type conversion mechanism that was different from the one in Spring MVC, which relied on the `java.beans.PropertyEditor` abstraction.
|
||||
Spring's' type conversion was actually influenced by Web Flow's own type conversion system.
|
||||
Spring's type conversion was actually influenced by Web Flow's own type conversion system.
|
||||
Hence, Web Flow users should find it natural to work with Spring type conversion.
|
||||
Another obvious and very important benefit of this change is that you can now use a single type conversion mechanism across Spring MVC And Spring Web Flow.
|
||||
Another obvious and important benefit of this change is that you can now use a single type conversion mechanism across Spring MVC And Spring Web Flow.
|
||||
|
||||
[[_converter_upgrade_to_spring_3]]
|
||||
==== Upgrading to Spring 3 Type Conversion And Formatting
|
||||
|
||||
What does this practically mean for existing applications? Existing applications are likely registering their own converters of type `org.springframework.binding.convert.converters.Converter` through a sub-class of `DefaultConversionService` available in Spring Binding.
|
||||
What does this mean, in practical terms, for existing applications? Existing applications are likely registering their own converters of type `org.springframework.binding.convert.converters.Converter` through a sub-class of `DefaultConversionService` available in Spring Binding.
|
||||
Those converters can continue to be registered as before.
|
||||
They has been adapted as the Spring `GenericConverter` types and registered with a Spring `org.springframework.core.convert.ConversionService` instance.
|
||||
They have been adapted as the Spring `GenericConverter` types and registered with a Spring `org.springframework.core.convert.ConversionService` instance.
|
||||
In other words, existing converters are invoked through Spring's type conversion service.
|
||||
|
||||
The only exception to this rule are named converters, which you can reference from a `binding` element in a `view-state`, as follows:
|
||||
@@ -226,7 +226,7 @@ However, this mechanism is deprecated, and applications are encouraged to favor
|
||||
Also note that the existing Spring Binding `DefaultConversionService` no longer registers any default converters.
|
||||
Instead, Web Flow now relies on the default type converters and formatters in Spring.
|
||||
|
||||
In summary, the Spring type conversion and formatting is now used almost exclusively in Web Flow.
|
||||
In summary, Spring type conversion and formatting is now used almost exclusively in Web Flow.
|
||||
Although existing applications should work without any changes, we encourage moving towards unifying the type conversion needs of Spring MVC and Spring Web Flow parts of applications.
|
||||
|
||||
[[_converter_configuration]]
|
||||
@@ -251,7 +251,7 @@ In Spring MVC, an instance of a `FormattingConversionService` is created automat
|
||||
----
|
||||
====
|
||||
|
||||
Internally that is done with the help of ``FormattingConversionServiceFactoryBean``, which registers a default set of converters and formatters.
|
||||
Internally, that is done with the help of ``FormattingConversionServiceFactoryBean``, which registers a default set of converters and formatters.
|
||||
You can customize the conversion service instance used in Spring MVC through the `conversion-service` attribute, as follows:
|
||||
|
||||
====
|
||||
@@ -275,7 +275,7 @@ You can customize the `DefaultConversionService` used in Web Flow through the fl
|
||||
----
|
||||
====
|
||||
|
||||
By connecting the dots in order to register your own formatters for use in both Spring MVC and in Spring Web Flow you can do the following:
|
||||
You can do the following to register your own formatters for use in both Spring MVC and in Spring Web Flow :
|
||||
|
||||
. Create a class to register your custom formatters:
|
||||
+
|
||||
@@ -292,7 +292,7 @@ public class ApplicationConversionServiceFactoryBean extends FormattingConversio
|
||||
}
|
||||
----
|
||||
====
|
||||
. Configure it for use in Spring MVC:
|
||||
. Configure the class for use in Spring MVC:
|
||||
+
|
||||
====
|
||||
[source,xml]
|
||||
@@ -319,7 +319,7 @@ public class ApplicationConversionServiceFactoryBean extends FormattingConversio
|
||||
<bean id="applicationConversionService" class="somepackage.ApplicationConversionServiceFactoryBean">
|
||||
----
|
||||
====
|
||||
. Connect the Web Flow `DefaultConversionService` to the same "applicationConversionService" bean used in Spring MVC:
|
||||
. Connect the Web Flow `DefaultConversionService` to the same `applicationConversionService` bean used in Spring MVC:
|
||||
+
|
||||
====
|
||||
[source,xml]
|
||||
@@ -340,7 +340,7 @@ You can register existing Spring Binding `Converter` types through the `defaultC
|
||||
|
||||
[[_converter_working_with]]
|
||||
==== Working With Spring Type Conversion And Formatting
|
||||
|
||||
``
|
||||
An important concept to understand is the difference between type converters and formatters.
|
||||
|
||||
Type converters in Spring, provided in ``org.springframework.core``, are for general-purpose type conversion between any two object types.
|
||||
@@ -359,7 +359,7 @@ In fact, `Formatters` are registered as `GenericConverter` types with Spring's `
|
||||
|
||||
One of the best features of the type conversion is the ability to use annotations for better control over formatting in a concise manner.
|
||||
You can place annotations on model attributes and on the arguments of `@Controller` methods that are mapped to requests.
|
||||
Spring provides two annotations (`@NumberFormat` and `@DateTimeFormat`), but you can create your own and have them registered along with the associated formatting logic.
|
||||
Spring provides two annotations (`@NumberFormat` and `@DateTimeFormat`), but you can create your own and have them be registered, along with the associated formatting logic.
|
||||
You can see examples of the `@DateTimeFormat` annotation in the https://src.springframework.org/svn/spring-samples/travel[Spring Travel] sample and in the https://src.springframework.org/svn/spring-samples/petcare[Petcare] sample, along with other samples in the https://src.springframework.org/svn/spring-samples[Spring Samples] repository.
|
||||
// TODO These URLs are wrong, but I can't find the right ones.
|
||||
|
||||
@@ -416,7 +416,7 @@ The following example uses a `binder` element:
|
||||
====
|
||||
|
||||
Each binding may also apply a converter to format the model property value for display in a custom manner.
|
||||
If no converter is specified, the default converter for the model property's type will be used.
|
||||
If no converter is specified, the default converter for the model property's type is used.
|
||||
The following example shows two `binding` elements with `converter` attributes:
|
||||
|
||||
====
|
||||
@@ -507,7 +507,7 @@ private String name;
|
||||
----
|
||||
====
|
||||
|
||||
In a flow definition, you can specify validation hints on a view state or on a transition, and those will be resolved to validation groups.
|
||||
In a flow definition, you can specify validation hints on a view state or on a transition, and those are resolved to validation groups.
|
||||
The following example defines validation hints:
|
||||
|
||||
====
|
||||
@@ -526,7 +526,7 @@ You can also provide fully qualified type names.
|
||||
|
||||
A hint with a value of `default` has a special meaning and is translated to the default validation group in Bean Validation: `javax.validation.groups.Default`.
|
||||
|
||||
A custom `ValidationHintResolver` can be configured, if necessary, through the `validationHintResolver` property of the `flow-builder-services` element, as follows:
|
||||
You can configure a custom `ValidationHintResolver`, if necessary, through the `validationHintResolver` property of the `flow-builder-services` element, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -551,7 +551,7 @@ Both ways provide you with a `ValidationContext` to record error messages and ac
|
||||
Defining validation logic in your model object is the simplest way to validate its state.
|
||||
Once such logic is structured according to Web Flow conventions, Web Flow automatically invokes that logic during the `view-state` postback lifecycle.
|
||||
Web Flow conventions have you structure model validation logic by `view-state`, letting you validate the subset of model properties that are editable on that view.
|
||||
To do this, create a public method with a name of `validate${state}`, where `${state}` is the ID of your `view-state` where you want validation to run.
|
||||
To do this, create a public method with a name of `validate${state}`, where `${state}` is the ID of your `view-state` for which you want validation to run.
|
||||
The following example performs model validation:
|
||||
|
||||
====
|
||||
@@ -588,15 +588,15 @@ The following example shows such a `view-state`:
|
||||
----
|
||||
====
|
||||
|
||||
Any number of validation methods are defined.
|
||||
You can define any number of validation methods.
|
||||
Generally, a flow edits a model over a series of views.
|
||||
In that case, you would define a validate method for each `view-state` where validation needs to run.
|
||||
In that case, you would define a validate method for each `view-state` for which validation needs to run.
|
||||
|
||||
[[_view_validation_programmatic_validator]]
|
||||
===== Implementing a Validator
|
||||
|
||||
The second way to perform programmatic validation is to define a separate object, called a _validator_, which validates your model object.
|
||||
To do this, first create a class whose name has the pattern `${model}Validator`, where `${model}` is the capitalized form of the model expression, such as `booking`.
|
||||
To do this, first create a class whose name has the pattern `${model}Validator`, where `${model}` is the capitalized form of the model expression, such as `Booking`.
|
||||
Then define a public method with a name of `validate${state}`, where `${state}` is the ID of your `view-state`, such as `enterBookingDetails`.
|
||||
The class should then be deployed as a Spring bean.
|
||||
Any number of validation methods can be defined.
|
||||
@@ -631,7 +631,7 @@ Then, any time the `booking` model needs to be validated, this `bookingValidator
|
||||
|
||||
===== Default Validate Method
|
||||
|
||||
A _validator_ class can also define a method called `validate` not associated (by convention) with any specific `view-state`.
|
||||
A _validator_ class can also define a method called `validate` that is not associated (by convention) with any specific `view-state`.
|
||||
The following example defines such a method:
|
||||
|
||||
====
|
||||
@@ -646,7 +646,7 @@ public class BookingValidator {
|
||||
----
|
||||
====
|
||||
|
||||
In the preceding code sample, the method `validate` is called every time a model of type `Booking` is validated (unless validation has been suppressed for that transition). If needed, the default method can also be called in addition to an existing state-specific method.
|
||||
In the preceding code sample, the `validate` method is called every time a model of type `Booking` is validated (unless validation has been suppressed for that transition). If needed, the default method can also be called in addition to an existing state-specific method.
|
||||
Consider the following example:
|
||||
|
||||
====
|
||||
@@ -672,7 +672,7 @@ The default `validate` method is called next.
|
||||
|
||||
A `ValidationContext` lets you obtain a `MessageContext` to record messages during validation.
|
||||
It also exposes information about the current user, such as the signaled `userEvent` and the current user's `Principal` identity.
|
||||
This information can be used to customize validation logic based on what button or link was activated in the UI or who is authenticated.
|
||||
You can use this information to customize validation logic based on what button or link was activated in the UI or who is authenticated.
|
||||
See the API Javadoc for https://docs.spring.io/spring-webflow/docs/current/api/org/springframework/binding/validation/ValidationContext.html[`ValidationContext`] for more information.
|
||||
|
||||
[[_view_validation_suppression]]
|
||||
@@ -700,7 +700,7 @@ A transition may take the user to another view, or it may run an action and re-r
|
||||
A transition may also request the rendering of parts of a view (called "`fragments`") when handling an Ajax event.
|
||||
Finally, you can also define "`global`" transitions that are shared across all views.
|
||||
|
||||
The following sections discuss how to implementing view transitions.
|
||||
The following sections discuss how to implement view transitions.
|
||||
|
||||
==== Transition Actions
|
||||
|
||||
@@ -708,8 +708,8 @@ A `view-state` transition can invoke one or more actions before running.
|
||||
These actions may return an error result to prevent the transition from exiting the current `view-state`.
|
||||
If an error result occurs, the view re-renders and should display an appropriate message to the user.
|
||||
|
||||
If the transition action invokes a plain Java method, the invoked method may return a boolean, whose value, `true` or `false`, indicates whether the transition should take place or be prevented from running.
|
||||
A method may also return a `String` where literal values of `success`, `yes`, or `true` indicate the transition should occur, and any other value means the opposite.
|
||||
If the transition action invokes a plain Java method, the invoked method may return a boolean, whose value (`true` or `false`) indicates whether the transition should take place or be prevented from running.
|
||||
A method can also return a `String` where literal values of `success`, `yes`, or `true` indicate the transition should occur, and any other value means the opposite.
|
||||
You can use this technique to handle exceptions thrown by service-layer methods.
|
||||
The following example invokes an action that calls a service and handles an exceptional situation:
|
||||
|
||||
@@ -738,7 +738,7 @@ public class BookingAction {
|
||||
----
|
||||
====
|
||||
|
||||
When there is more than one action defined on a transition, if one returns an error result. the remaining actions in the set are _not_ executed.
|
||||
When there is more than one action defined on a transition, if one returns an error result, the remaining actions in the set are _not_ executed.
|
||||
If you need to ensure one transition action's result cannot impact the execution of another, define a single transition action that invokes a method that encapsulates all the action logic.
|
||||
|
||||
[[_event_handlers_global]]
|
||||
@@ -793,7 +793,7 @@ You can use the `render` element within a transition to request partial re-rende
|
||||
----
|
||||
====
|
||||
|
||||
The `fragments` attribute should reference the ID(s) of the view element(s) you wish to re-render.
|
||||
The `fragments` attribute should reference the IDs of the view elements you wish to re-render.
|
||||
You can specify multiple elements to re-render by separating them with a comma delimiter.
|
||||
|
||||
Such partial rendering is often used with events signaled by Ajax to update a specific zone of the view.
|
||||
@@ -802,7 +802,7 @@ Such partial rendering is often used with events signaled by Ajax to update a sp
|
||||
=== Working with Messages
|
||||
|
||||
Spring Web Flow's `MessageContext` is an API for recording messages during the course of flow executions.
|
||||
Plain text messages can be added to the context, as well as internationalized messages resolved by a Spring `MessageSource`.
|
||||
You can add plain text messages to the context, as well as internationalized messages resolved by a Spring `MessageSource`.
|
||||
Messages are renderable by views and automatically survive flow execution redirects.
|
||||
Three distinct message severities are provided: `info`, `warning`, and `error`.
|
||||
In addition, a convenient `MessageBuilder` exists for fluently constructing messages.
|
||||
@@ -850,7 +850,7 @@ context.addMessage(builder.info().code("reservationConfirmation").build());
|
||||
==== Using Message Bundles
|
||||
|
||||
Internationalized messages are defined in message bundles accessed by a Spring `MessageSource`.
|
||||
To create a flow-specific message bundle, define `messages.properties` file(s) in your flow's directory.
|
||||
To create a flow-specific message bundle, define `messages.properties` files in your flow's directory.
|
||||
Create a default `messages.properties` file and a `.properties` file for each additional `Locale` you need to support.
|
||||
The following example defines a few messages:
|
||||
|
||||
@@ -929,7 +929,7 @@ You can use the `popup` attribute to render a view in a modal popup dialog, as f
|
||||
----
|
||||
====
|
||||
|
||||
When using Web Flow with the Spring Javascript, no client side code is necessary for the popup to display.
|
||||
When using Web Flow with the Spring Javascript library, no client-side code is necessary for the popup to display.
|
||||
Web Flow sends a response to the client to request a redirect to the view from a popup, and the client honors the request.
|
||||
|
||||
=== View Backtracking
|
||||
@@ -952,7 +952,7 @@ You can set the `history` attribute to `discard` to prevent backtracking to a vi
|
||||
[[_history_invalidate]]
|
||||
==== Invalidating History
|
||||
|
||||
You can set the `history` attribute to `invalidate` to prevent backtracking to a view as well all previously displayed views, as follows:
|
||||
You can set the `history` attribute to `invalidate` to prevent backtracking to a view as well as all previously displayed views, as follows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
|
||||
@@ -12,12 +12,12 @@ This section covers the changes that have been included in the last few versions
|
||||
=== Spring Web Flow 2.5
|
||||
|
||||
This release provides an upgrade path to Spring Framework 5 that in turn requires Java 8+, Servlet 3.1, Hibernate 5, Tiles 3.
|
||||
See the https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x[Spring Framework wiki] for more details.
|
||||
See the https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-5.x[Spring Framework wiki] for more details.
|
||||
The https://github.com/spring-projects/spring-webflow-samples[samples repository] has been upgraded to Spring Web Flow 2.5.
|
||||
|
||||
As of 2.5, there is no longer a `spring-js` module.
|
||||
The classes from that module have been kept but moved to new packages in the `spring-webflow` module.
|
||||
The `spring-js-resources` module is available as an optional module that you explicitly include.
|
||||
The `spring-js-resources` module is available as an optional module that you can explicitly include.
|
||||
|
||||
This release requires JSF 2.2 or higher.
|
||||
|
||||
@@ -194,7 +194,7 @@ The following features that were not supported in 2.1 are now available:
|
||||
* JSF 2 resource request handling
|
||||
* JSF 2 Ajax requests
|
||||
|
||||
At this point, support for JSF 2 is considered comprehensive although not it does not cover every JSF 2 feature.
|
||||
At this point, support for JSF 2 is considered comprehensive, although not it does not cover every JSF 2 feature.
|
||||
The excluded items are mostly features that overlap with the core value that Web Flow provides, such as those relating to navigation and state management.
|
||||
|
||||
See <<_spring_faces_webflow_config>> for important configuration changes.
|
||||
@@ -252,7 +252,7 @@ The `spring-js` artifact has been split in two. The new artifact (`spring-js-res
|
||||
|
||||
Applications preparing their own custom Dojo build have an option now to avoid including `spring-js-resources` and put `Spring.js` and `Spring-Dojo.js` directly under the root of their web application.
|
||||
|
||||
===== Client resources moved into META-INF/web-resources
|
||||
===== Client Resources Moved into META-INF/web-resources
|
||||
|
||||
Bundled client resources (`.js`, `.css`, and so on) have been moved to `META-INF/web-resources` from their previous location under `META-INF`.
|
||||
This change is transparent for applications but results in simpler and safer configuration when using the new resource handling mechanism available in Spring 3.0.4.
|
||||
|
||||
Reference in New Issue
Block a user