diff --git a/spring-webflow-reference/src/defining-flows.xml b/spring-webflow-reference/src/defining-flows.xml index e6221a70..dc64b8a2 100644 --- a/spring-webflow-reference/src/defining-flows.xml +++ b/spring-webflow-reference/src/defining-flows.xml @@ -64,14 +64,14 @@ Every flow begins with the following root element: - -<?xml version="1.0" encoding="UTF-8"?> -<flow xmlns="http://www.springframework.org/schema/webflow" + + -</flow> +]]> All states of the flow are defined within this element. @@ -83,8 +83,8 @@ Use the view-state element to define a step of the flow that renders a view: - -<view-state id="enterBookingDetails" /> + ]]> By convention, a view-state maps its id to a view template in the directory where the flow is located. @@ -97,10 +97,10 @@ Use the transition element to handle events that occur within a state: - -<view-state id="enterBookingDetails"> - <transition on="submit" to="reviewBooking" /> -</view-state> + + +]]> These transitions drive view navigations. @@ -111,8 +111,8 @@ Use the end-state element to define a flow outcome: - -<end-state id="bookingCancelled" /> + ]]> When a flow transitions to a end-state it terminates and the outcome is returned. @@ -125,27 +125,27 @@ Teams often do this before adding flow behaviors so they can focus on developing the user interface of the application with end users first. Below is a sample flow that implements its view navigation logic using these elements: - -<flow xmlns="http://www.springframework.org/schema/webflow" + - <view-state id="enterBookingDetails"> - <transition on="submit" to="reviewBooking" /> - </view-state> + + + - <view-state id="reviewBooking"> - <transition on="confirm" to="bookingConfirmed" /> - <transition on="revise" to="enterBookingDetails" /> - <transition on="cancel" to="bookingCancelled" /> - </view-state> + + + + + - <end-state id="bookingConfirmed" /> + - <end-state id="bookingCancelled" /> + -</flow> +]]> @@ -178,16 +178,16 @@ With this single tag you can invoke methods on Spring beans or any other flow variable. For example: - -<evaluate expression="entityManager.persist(booking)" /> + ]]> Assigning an evaluate result If the expression returns a value, that value can be saved in the flow's data model called flowScope: - -<evaluate expression="bookingService.findHotels(searchCriteria)" result="flowScope.hotels" /> + ]]> @@ -195,9 +195,9 @@ If the expression returns a value that may need to be converted, specify the desired type using the result-type attribute: - -<evaluate expression="bookingService.findHotels(searchCriteria)" result="flowScope.hotels" - result-type="dataModel"/> + ]]> @@ -206,34 +206,34 @@ Now review the sample booking flow with actions added: - -<flow xmlns="http://www.springframework.org/schema/webflow" + - <input name="hotelId" /> + - <on-start> - <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" - result="flowScope.booking" /> - </on-start> + + + - <view-state id="enterBookingDetails"> - <transition on="submit" to="reviewBooking" /> - </view-state> + + + - <view-state id="reviewBooking"> - <transition on="confirm" to="bookingConfirmed" /> - <transition on="revise" to="enterBookingDetails" /> - <transition on="cancel" to="bookingCancelled" /> - </view-state> + + + + + - <end-state id="bookingConfirmed" /> + - <end-state id="bookingCancelled" /> + -</flow> +]]> This flow now creates a Booking object in flow scope when it starts. @@ -248,25 +248,25 @@ Flows can be passed input attributes when they start, and can return output attributes when they end. In this respect, calling a flow is conceptually similar to calling a method with the following signature: - -FlowOutcome flowId(Map<String, Object> inputAttributes); + inputAttributes);]]> ... where a FlowOutcome has the following signature: - + getOutputAttributes(); +}]]> input Use the input element to declare a flow input attribute: - -<input name="hotelId" /> + ]]> Input values are saved in flow scope under the name of the attribute. @@ -276,8 +276,8 @@ public interface FlowOutcome { Use the type attribute to declare the input attribute's type: - -<input name="hotelId" type="long" /> + ]]> If an input value does not match the declared type, a type conversion will be attempted. @@ -287,8 +287,8 @@ public interface FlowOutcome { Use the value attribute to specify an expression to assign the input value to: - -<input name="hotelId" value="flowScope.myParameterObject.hotelId" /> + ]]> If the expression's value type can be determined, that metadata will be used for type coersion if no type attribute is specified. @@ -298,8 +298,8 @@ public interface FlowOutcome { Use the required attribute to enforce the input is not null or empty: - -<input name="hotelId" type="long" value="flowScope.hotelId" required="true" /> + ]]> @@ -309,10 +309,10 @@ public interface FlowOutcome { Use the output element to declare a flow output attribute. Output attributes are declared within end-states that represent specific flow outcomes. - -<end-state id="bookingConfirmed"> - <output name="bookingId" /> -</end-state> + + +]]> Output values are obtained from flow scope under the name of the attribute. @@ -322,8 +322,8 @@ public interface FlowOutcome { Use the value attribute to denote a specific output value expression: - -<output name="confirmationNumber" value="booking.confirmationNumber" /> + ]]> @@ -332,36 +332,36 @@ public interface FlowOutcome { Now review the sample booking flow with input/output mapping: - -<flow xmlns="http://www.springframework.org/schema/webflow" + ; - <input name="hotelId" /> + - <on-start> - <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" - result="flowScope.booking" /> - </on-start> + + + - <view-state id="enterBookingDetails"> - <transition on="submit" to="reviewBooking" /> - </view-state> + + + - <view-state id="reviewBooking"> - <transition on="confirm" to="bookingConfirmed" /> - <transition on="revise" to="enterBookingDetails" /> - <transition on="cancel" to="bookingCancelled" /> - </view-state> + + + + + - <end-state id="bookingConfirmed" > - <output name="bookingId" value="booking.id"/> - </end-state> + + + - <end-state id="bookingCancelled" /> + -</flow> +]]> The flow now accepts a hotelId input attribute and returns a bookingId output attribute @@ -381,8 +381,8 @@ public interface FlowOutcome { Use the var element to declare a flow variable: - -<var name="searchCriteria" class="com.mycompany.myapp.hotels.search.SearchCriteria"/> + ]]> Make sure your variable's class implements java.io.Serializable, as the instance state is saved between flow requests. @@ -399,13 +399,13 @@ public interface FlowOutcome { Use the subflow-state element to call another flow as a subflow: - -<subflow-state id="addGuest" subflow="createGuest"> - <transition on="guestCreated" to="reviewBooking"> - <evaluate expression="booking.guests.add(currentEvent.guest)" /> - <transition /> - <transition on="creationCancelled" to="reviewBooking" /> -</subfow-state> + + + + + +]]> The above example calls the createGuest flow, then waits for it to return. @@ -416,11 +416,11 @@ public interface FlowOutcome { Use the input element to pass input to the subflow: - -<subflow-state id="addGuest" subflow="createGuest"> - <input name="booking" /> - <transition to="reviewBooking" /> -</subfow-state> + + + +]]> @@ -428,10 +428,10 @@ public interface FlowOutcome { Simply refer to a subflow output attribute by its name within a outcome transition: - -<transition on="guestCreated" to="reviewBooking"> - <evaluate expression="booking.guests.add(guest)"/> -<transition /> + + +]]> In the above example, guest is the name of an output attribute returned by the guestCreated outcome. @@ -443,44 +443,44 @@ public interface FlowOutcome { Now review the sample booking flow calling a subflow: - -<flow xmlns="http://www.springframework.org/schema/webflow" + - <input name="hotelId" /> + - <on-start> - <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" - result="flowScope.booking" /> - </on-start> + + + - <view-state id="enterBookingDetails"> - <transition on="submit" to="reviewBooking" /> - </view-state> + + + - <view-state id="reviewBooking"> - <transition on="addGuest" to="addGuest" /> - <transition on="confirm" to="bookingConfirmed" /> - <transition on="revise" to="enterBookingDetails" /> - <transition on="cancel" to="bookingCancelled" /> - </view-state> + + + + + + - <subflow-state id="addGuest" subflow="createGuest"> - <transition on="guestCreated" to="reviewBooking"> - <evaluate expression="booking.guests.add(guest)"/> - <transition /> - <transition on="creationCancelled" to="reviewBooking" /> - </subfow-state> + + + + + + - <end-state id="bookingConfirmed" > - <output name="bookingId" value="booking.id"/> - </end-state> + + + - <end-state id="bookingCancelled" /> + -</flow> +]]> The flow now calls a createGuest subflow to add a new guest to the guest list.