diff --git a/spring-webflow-reference/src/defining-flows.xml b/spring-webflow-reference/src/defining-flows.xml index dc64b8a2..e510bae2 100644 --- a/spring-webflow-reference/src/defining-flows.xml +++ b/spring-webflow-reference/src/defining-flows.xml @@ -197,7 +197,7 @@ ]]> + result-type="dataModel"/>]]> @@ -216,7 +216,7 @@ + result="flowScope.booking" /> @@ -342,7 +342,7 @@ public interface FlowOutcome { + result="flowScope.booking" /> @@ -453,7 +453,7 @@ public interface FlowOutcome { + result="flowScope.booking" /> diff --git a/spring-webflow-reference/src/el.xml b/spring-webflow-reference/src/el.xml index bb58fc0b..29a3e79e 100644 --- a/spring-webflow-reference/src/el.xml +++ b/spring-webflow-reference/src/el.xml @@ -65,8 +65,8 @@ Such expressions are dynamically evaluated by the EL and should not be enclosed in delimiters like ${} or #{}. For example: - -<evaluate expression="searchCriteria.nextPage()" /> + ]]> The expression above is a standard expression that invokes the nextPage method on the searchCriteria variable when evaluated. @@ -84,8 +84,8 @@ Each eval block is explictly delimited with the ${} delimiters. For example: - -<view-state id="error" view="error-${externalContext.locale}.xhtml" /> + ]]> The expression above is a template expression. @@ -110,8 +110,8 @@ Use flowScope to assign a flow variable. Flow scope gets allocated when a flow starts and destroyed when the flow ends. - -<evaluate expression="searchService.findHotel(hotelId)" result="flowScope.hotel" /> + ]]> @@ -121,11 +121,11 @@ View scope gets allocated when a view-state enters and destroyed when the state exits. View scope is only referenceable from within a view-state. - -<on-render> - <evaluate expression="searchService.findHotels(searchCriteria)" result="viewScope.hotels" - type="dataModel" /> -</on-render> + + +]]> @@ -134,8 +134,8 @@ Use requestScope to assign a request variable. Request scope gets allocated when a flow is called and destroyed when the flow returns. - -<set name="requestScope.hotelId" value="requestParameters.id" type="long" /> + ]]> @@ -144,8 +144,8 @@ Use flashScope to assign a flash variable. Flash scope gets allocated when a flow starts, cleared after every view render, and destroyed when the flow ends. - -<set name="flashScope.statusMessage" value="'Booking confirmed'" /> + ]]> @@ -155,8 +155,8 @@ 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 subflows. - -<evaluate expression="searchService.findHotel(hotelId)" result="conversationScope.hotel" /> + ]]> @@ -164,8 +164,8 @@ Use requestParameters to access a client request parameter: - -<set name="requestScope.hotelId" value="requestParameters.id" type="long" /> + ]]> @@ -173,8 +173,8 @@ Use currentEvent to access attributes of the current Event: - -<evaluate expression="booking.guests.add(currentEvent.guest)" /> + ]]> @@ -182,9 +182,9 @@ Use currentUser to access the authenticated Principal: - -<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" - result="flowScope.booking" /> + ]]> @@ -193,8 +193,8 @@ Use messageContext to access a context for retrieving and creating flow execution messages, including error and success messages. See the MessageContext Javadocs for more information. - -<evaluate expression="bookingValidator.validate(booking, messageContext)" /> + ]]> @@ -223,9 +223,9 @@ Use externalContext to access the client environment, including user session attributes. See the ExternalContext API JavaDocs for more information. - -<evaluate expression="searchService.suggestHotels(externalContext.sessionMap.userProfile)" - result="viewScope.hotels" /> + ]]> @@ -235,15 +235,15 @@ When assigning a variable in one of the flow scopes, referencing that scope is required. For example: - -<set name="requestScope.hotelId" value="requestParameters.id" type="long" /> + ]]> When simply accessing a variable in one of the scopes, referencing the scope is optional. For example: - -<evaluate expression="entityManager.persist(booking)" /> + ]]> If no scope is specified, like in the use of booking above, a scope searching algorithm will be employed. diff --git a/spring-webflow-reference/src/flow-definition-field-mappings.xml b/spring-webflow-reference/src/flow-definition-field-mappings.xml index ffce8972..b6ec22cd 100644 --- a/spring-webflow-reference/src/flow-definition-field-mappings.xml +++ b/spring-webflow-reference/src/flow-definition-field-mappings.xml @@ -7,7 +7,7 @@ While most of the changes are semantic, there are a few structural changes. Please see the upgrade guide for more details about changes between Web Flow 1.0 and 2.0. - +
Mappings diff --git a/spring-webflow-reference/src/flow-inheritance.xml b/spring-webflow-reference/src/flow-inheritance.xml index 38267106..677a973c 100644 --- a/spring-webflow-reference/src/flow-inheritance.xml +++ b/spring-webflow-reference/src/flow-inheritance.xml @@ -37,8 +37,8 @@ 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. - -<flow parent="common-transitions, common-states"> + ]]> @@ -55,8 +55,8 @@ The parent and child states must be of the same type. For instance a view-state cannot inherit from an end-state, only another view-state. - -<view-state id="child-state" parent="parent-flow#parent-view-state"> + ]]> @@ -67,8 +67,8 @@ In order to protect these flow from running, they can be marked as abstract. If an abstract flow attempts to run, a FlowBuilderException will be thrown. - -<flow abstract="true"> + ]]> diff --git a/spring-webflow-reference/src/flow-security.xml b/spring-webflow-reference/src/flow-security.xml index bbf1d54c..f00c0482 100644 --- a/spring-webflow-reference/src/flow-security.xml +++ b/spring-webflow-reference/src/flow-security.xml @@ -42,8 +42,8 @@ Often, these are specific security roles. The attributes are compared against the user's granted attributes by a Spring Security access decision manager. - -<secured attributes="ROLE_USER" /> + ]]> By default, a role based access decision manager is used to determine if the user is allowed access. @@ -57,8 +57,8 @@ Any, allows access if at least one of the required security attributes is granted to the user. All, allows access only if each of the required security attributes are granted to the user. - -<secured attributes="ROLE_USER, ROLE_ANONYMOUS" match="any" /> + ]]> This attribute is optional. @@ -121,33 +121,33 @@ The Spring configuration defines http specifics (such as protected URLs and login/logout mechanics) and the authentication-provider. For the sample applications, a local authentication provider is configured. - -<security:http auto-config="true"> - <security:intercept-url pattern="/spring/login*" access="ROLE_ANONYMOUS" /> - <security:intercept-url pattern="/spring/logout-success*" access="ROLE_ANONYMOUS" /> - <security:intercept-url pattern="/spring/logout*" access="ROLE_USER" /> + + + + - <security:form-login login-page="/spring/login" + - <security:logout logout-url="/spring/logout" logout-success-url="/spring/logout-success" /> -</security:http> + + -<security:authentication-provider> - <security:password-encoder hash="md5" /> - <security:user-service> - <security:user name="keith" password="417c7382b16c395bc25b5da1398cf076" - authorities="ROLE_USER,ROLE_SUPERVISOR" /> - <security:user name="erwin" password="12430911a8af075c6f41c6976af22b09" - authorities="ROLE_USER,ROLE_SUPERVISOR" /> - <security:user name="jeremy" password="57c6cbff0d421449be820763f03139eb" - authorities="ROLE_USER" /> - <security:user name="scott" password="942f2339bf50796de535a384f0d1af3e" - authorities="ROLE_USER" /> - </security:user-service> -</security:authentication-provider> + + + + + + + + +]]> @@ -157,16 +157,16 @@ This filter will listen for login/logout requests and process them accordingly. It will also catch AccesDeniedExceptions and redirect the user to the login page. - -<filter> - <filter-name>springSecurityFilterChain</filter-name> - <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> -</filter> + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + -<filter-mapping> - <filter-name>springSecurityFilterChain</filter-name> - <url-pattern>/*</url-pattern> -</filter-mapping> + + springSecurityFilterChain + /* +]]> diff --git a/spring-webflow-reference/src/system-setup.xml b/spring-webflow-reference/src/system-setup.xml index 6cd35eba..b171b88d 100644 --- a/spring-webflow-reference/src/system-setup.xml +++ b/spring-webflow-reference/src/system-setup.xml @@ -13,19 +13,19 @@ Web Flow provides a Spring schema that allows you to configure the system. To use this schema, include it in one of your infrastructure-layer beans files: - -<beans xmlns="http://www.springframework.org/schema/beans" + - <!-- Setup Web Flow here --> + -</beans> +]]> @@ -38,10 +38,10 @@ Register your flows in a FlowRegistry: - -<webflow:flow-registry id="flowRegistry"> - <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" /> -</webflow:flow-registry> + + +]]> @@ -49,8 +49,8 @@ Deploy a FlowExecutor, the central service for executing flows: - -<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry" /> + ]]> @@ -66,28 +66,28 @@ If no flow-builder-services tag is specified, the default service implementations are used. When the tag is defined, you only need to reference the services you want to customize. - -<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices"> - <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" /> -</webflow:flow-registry> + + + -<webflow:flow-builder-services id="flowBuilderServices" /> +]]> The configurable services are the conversion-service, formatter-registry, expression-parser, and view-factory-creator. These services are configured by referencing custom beans you define. For example: - -<webflow:flow-builder-services id="flowBuilderServices" - conversion-service="conversionService" - formatter-registry="formatterRegistry" - expression-parser="expressionParser" - view-factory-creator="viewFactoryCreator"/> + -<bean id="conversionService" class="..." /> -<bean id="formatterRegistry" class="..." /> -<bean id="expressionParser" class="..." /> -<bean id="viewFactoryCreator" class="..." /> + + + +]]> conversion-service @@ -126,16 +126,16 @@ Use the parent attribute to link two flow registries together in a hierarchy. When the child registry is queried, if it cannot find the requested flow it will delegate to its parent. - -<!-- my-system-config.xml --> -<webflow:flow-registry id="flowRegistry" parent="sharedFlowRegistry"> - <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" /> -</webflow:flow-registry> + + + + -<!-- shared-config.xml --> -<webflow:flow-registry id="sharedFlowRegistry"> - <-- Global flows shared by several applications --< -</webflow:flow-registry> + + + <-- Global flows shared by several applications --> +]]> @@ -144,8 +144,8 @@ Use the location element to specify paths to flow definitions to register. By default, flows will be assigned registry identifiers equal to their filenames minus the file extension. - -<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" /> + ]]> @@ -153,8 +153,8 @@ Specify an id to assign a custom registry identifier to a flow: - -<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" id="bookHotel" /> + ]]> @@ -162,13 +162,13 @@ Use the flow-definition-attributes element to assign custom meta-attributes to a registered flow: - -<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml"> - <flow-definition-attributes> - <attribute name="caption" value="Books a hotel" /> - <attribute name="persistence-context" value="true" type="boolean" /> - </flow-definition-attributes> -</webflow:flow-location> + + + + + +]]> @@ -176,8 +176,8 @@ Use the flow-location-patterns element to register flows that match a specific resource location pattern: - -<webflow:flow-location-pattern value="/WEB-INF/flows/**/*-flow.xml" /> + ]]> @@ -188,17 +188,17 @@ Use the flow-execution-listeners element to register listeners that observe the lifecycle of flow executions: - -<flow-execution-listeners> - <listener ref="securityListener"/> - <listener ref="persistenceListener"/> -</flow-execution-listeners> + + + +]]> You may also configure a listener to observe only certain flows: - -<listener ref="securityListener" criteria="securedFlow1,securedFlow2"/> + ]]> @@ -206,8 +206,8 @@ Use the flow-execution-repository element to tune flow execution persistence settings: - -<flow-execution-repository max-conversations="5" max-snapshots="30" /> + ]]> max-conversations diff --git a/spring-webflow-reference/src/testing.xml b/spring-webflow-reference/src/testing.xml index b1c325ce..3fcdf44f 100644 --- a/spring-webflow-reference/src/testing.xml +++ b/spring-webflow-reference/src/testing.xml @@ -12,10 +12,10 @@ To test the execution of a XML-based flow definition, extend AbstractXmlFlowExecutionTests: - + @@ -23,11 +23,11 @@ public class BookingFlowExecutionTests extends AbstractXmlFlowExecutionTests { At a minimum, you must override getResource(FlowDefinitionResourceFactory) to return the path to the flow you wish to test: - + @@ -36,11 +36,11 @@ protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resou If your flow has dependencies on externally managed services, also override configureFlowBuilderContext(MockFlowBuilderContext) to register stubs or mocks of those services: - + @@ -48,7 +48,7 @@ protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext Have your first test exercise the startup of your flow: - + Assertions generally verify the flow is in the correct state you expect. @@ -74,7 +74,7 @@ public void testStartBookingFlow() { 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. - + @@ -95,7 +95,7 @@ public void testEnterBookingDetails_Proceed() { To test calling a subflow, register a mock implementation of the subflow that asserts input was passed in correctly and returns the correct outcome for your test scenario. - + \ No newline at end of file diff --git a/spring-webflow-reference/src/views.xml b/spring-webflow-reference/src/views.xml index e89f383b..2bd2a330 100644 --- a/spring-webflow-reference/src/views.xml +++ b/spring-webflow-reference/src/views.xml @@ -12,10 +12,10 @@ Use the view-state element to define a step of the flow that renders a view and waits for a user event to resume: - -<view-state id="enterBookingDetails" > - <transition on="submit" to="reviewBooking" /> -</view-state> + + +]]> By convention, a view-state maps its id to a view template in the directory where the flow is located. @@ -47,8 +47,8 @@ The view id may be a relative path to view resource in the flow's working directory: - -<view-state id="enterBookingDetails" view="bookingDetails.xhtml"> + ]]> @@ -56,8 +56,8 @@ The view id may be a absolute path to a view resource in the webapp root directory: - -<view-state id="enterBookingDetails" view="/WEB-INF/hotels/booking/bookingDetails.xhtml"> + ]]> @@ -65,8 +65,8 @@ With some view frameworks, such as Spring MVC's view framework, the view id may also be a logical identifier resolved by the framework: - -<view-state id="enterBookingDetails" view="bookingDetails"> + ]]> See the Spring MVC integration section for more information on how to integrate with the MVC ViewResolver infrastructure. @@ -87,8 +87,8 @@ Use the var tag to declare a view variable. Like a flow variable, any @Autowired references are automatically restored when the view state resumes. - -<var name="searchCriteria" class="com.mycompany.myapp.hotels.SearchCriteria" /> + ]]> @@ -96,11 +96,10 @@ Use the on-render tag to assign a variable from an action result before the view renders: - -<on-render> - <evaluate expression="bookingService.findHotels(searchCriteria)" - result="viewScope.hotels" result-type="dataModel" /> -</on-render> + + +]]> @@ -111,21 +110,20 @@ The list is updated in view scope before each render. Asynchronous event handlers modify the current data page, then request re-rendering of the search results fragment. - -<view-state id="searchResults"> - <on-render> - <evaluate expression="bookingService.findHotels(searchCriteria)" - result="viewScope.hotels" result-type="dataModel" /> - </on-render> - <transition on="next"> - <evaluate expression="searchCriteria.nextPage()" /> - <render fragments="searchResultsTFragment" /> - </transition> - <transition on="previous"> - <evaluate expression="searchCriteria.previousPage()" /> - <render fragments="searchResultsFragment" /> - </transition> -</view-state> + + + + + + + + + + + + +]]> @@ -135,11 +133,10 @@ Use the on-render element to execute one or more actions before view rendering. Render actions are executed on the initial render as well as any subsequent refreshes, including any partial re-renderings of the view. - -<on-render> - <evaluate expression="bookingService.findHotels(searchCriteria)" - result="viewScope.hotels" result-type="dataModel" /> -</on-render> + + +]]> @@ -149,8 +146,8 @@ This attribute is typically used with views that render data controls, such as forms. The following example declares the enterBookingDetails state manipulates the booking model: - -<view-state id="enterBookingDetails" model="booking"> + ]]> The model may be in any accessible scope, such as flowScope or viewScope. @@ -175,11 +172,11 @@ Use the bind attribute to suppress model binding and validation for particular view events. - -<view-state id="enterBookingDetails"> - <transition on="proceed" to="reviewBooking"> - <transition on="cancel" to="bookingCancelled" bind="false" /> -</view-state> + + + +]]> @@ -197,11 +194,11 @@ Implementing a model validate method The first way is to define a validate method on the model object class. - To do this, create a public method with the name validate<state>, where state is the id of the view-state. + To do this, create a public method with the name validate, where state is the id of the view-state. The method must declare a MessageContext parameter for recording validation error messages. For example: - + Implementing a Validator The second way is to define a separate object, called a Validator, which validates your model object. - To do this, create a class that defines a public method with the name validate<state>, where state is the id of the view-state. + To do this, create a class that defines a public method with the name validate, where state is the id of the view-state. The method must declare a Object parameter to accept your model object, and a MessageContext parameter for recording validation error messages. For example: - + A Validator can also accept a Spring MVC Errors object, which is required for invoking existing Spring Validators. @@ -247,10 +244,10 @@ public class BookingValidator { From a view-state, transitions without targets can also be defined. Such transitions are called "event handlers": - -<transition on="event"> - <-- Handle event --> -</transition> + + <-- Handle event --> +]]> These event handlers do not change the state of the flow. @@ -261,11 +258,11 @@ public class BookingValidator { Use the render element to request partial re-rendering of a view after handling an event: - -<transition on="next"> - <evaluate expression="searchCriteria.nextPage()" /> - <render fragments="searchResultsFragment" /> -</transition> + + + +]]> The fragments attribute should reference the ID(s) of the view element(s) you wish to re-render. @@ -281,11 +278,11 @@ public class BookingValidator { Use the flow's global-transitions element to create event handlers that apply across all views. Global-transitions are often used to handle global menu links that are part of the layout. - -<global-transitions> - <transition on="login"> to="login"> - <transition on="logout"> to="logout"> -</global-transitions> + + to="login"> + to="logout"> +]]> @@ -300,7 +297,7 @@ public class BookingValidator { Adding plain text messages - + Adding internationalized messages - + @@ -331,11 +328,11 @@ context.addMessage(builder.info().code("reservationConfirmation").build()); To create a flow-specific message bundle, simply define messages.properties file(s) in your flow's directory. Create a default messages.properties file and a .properties file for each additional Locale you need to support. - + @@ -344,8 +341,8 @@ reservationConfirmation=We have processed your reservation - thank you and enjoy Use the popup attribute to render a view in a modal popup dialog: - -<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true"> + ]]> When using Web Flow with the Spring Javascript, no client side code is necessary for the popup to display. @@ -363,8 +360,8 @@ reservationConfirmation=We have processed your reservation - thank you and enjoy Set the history attribute to discard to prevent backtracking to a view: - -<view-state id="changeSearchCriteria" history="discard"> + ]]> @@ -372,8 +369,8 @@ reservationConfirmation=We have processed your reservation - thank you and enjoy Set the history attribute to invalidate to prevent backtracking to a view as well all previously displayed views: - -<view-state id="changeSearchCriteria" history="invalidate"> + ]]>