CDATA
This commit is contained in:
@@ -197,7 +197,7 @@
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<evaluate expression="bookingService.findHotels(searchCriteria)" result="flowScope.hotels"
|
||||
result-type="dataModel"/>]]>
|
||||
result-type="dataModel"/>]]>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
</sect2>
|
||||
@@ -216,7 +216,7 @@
|
||||
|
||||
<on-start>
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)"
|
||||
result="flowScope.booking" />
|
||||
result="flowScope.booking" />
|
||||
</on-start>
|
||||
|
||||
<view-state id="enterBookingDetails">
|
||||
@@ -342,7 +342,7 @@ public interface FlowOutcome {
|
||||
|
||||
<on-start>
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)"
|
||||
result="flowScope.booking" />
|
||||
result="flowScope.booking" />
|
||||
</on-start>
|
||||
|
||||
<view-state id="enterBookingDetails">
|
||||
@@ -453,7 +453,7 @@ public interface FlowOutcome {
|
||||
|
||||
<on-start>
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)"
|
||||
result="flowScope.booking" />
|
||||
result="flowScope.booking" />
|
||||
</on-start>
|
||||
|
||||
<view-state id="enterBookingDetails">
|
||||
|
||||
@@ -65,8 +65,8 @@
|
||||
Such expressions are dynamically evaluated by the EL and should not be enclosed in delimiters like <code>${}</code> or <code>#{}</code>.
|
||||
For example:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<evaluate expression="searchCriteria.nextPage()" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<evaluate expression="searchCriteria.nextPage()" />]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
The expression above is a standard expression that invokes the <code>nextPage</code> method on the <code>searchCriteria</code> variable when evaluated.
|
||||
@@ -84,8 +84,8 @@
|
||||
Each eval block is explictly delimited with the <code>${}</code> delimiters.
|
||||
For example:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<view-state id="error" view="error-${externalContext.locale}.xhtml" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<view-state id="error" view="error-${externalContext.locale}.xhtml" />]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
The expression above is a template expression.
|
||||
@@ -110,8 +110,8 @@
|
||||
Use <code>flowScope</code> to assign a flow variable.
|
||||
Flow scope gets allocated when a flow starts and destroyed when the flow ends.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<evaluate expression="searchService.findHotel(hotelId)" result="flowScope.hotel" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<evaluate expression="searchService.findHotel(hotelId)" result="flowScope.hotel" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-viewScope">
|
||||
@@ -121,11 +121,11 @@
|
||||
View scope gets allocated when a <code>view-state</code> enters and destroyed when the state exits.
|
||||
View scope is <emphasis>only</emphasis> referenceable from within a <code>view-state</code>.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<on-render>
|
||||
<evaluate expression="searchService.findHotels(searchCriteria)" result="viewScope.hotels"
|
||||
type="dataModel" />
|
||||
</on-render>
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<on-render>
|
||||
<evaluate expression="searchService.findHotels(searchCriteria)" result="viewScope.hotels"
|
||||
result-type="dataModel" />
|
||||
</on-render>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-requestScope">
|
||||
@@ -134,8 +134,8 @@
|
||||
Use <code>requestScope</code> to assign a request variable.
|
||||
Request scope gets allocated when a flow is called and destroyed when the flow returns.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<set name="requestScope.hotelId" value="requestParameters.id" type="long" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<set name="requestScope.hotelId" value="requestParameters.id" type="long" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-flashScope">
|
||||
@@ -144,8 +144,8 @@
|
||||
Use <code>flashScope</code> to assign a flash variable.
|
||||
Flash scope gets allocated when a flow starts, cleared after every view render, and destroyed when the flow ends.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<set name="flashScope.statusMessage" value="'Booking confirmed'" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<set name="flashScope.statusMessage" value="'Booking confirmed'" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-conversationScope">
|
||||
@@ -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.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<evaluate expression="searchService.findHotel(hotelId)" result="conversationScope.hotel" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<evaluate expression="searchService.findHotel(hotelId)" result="conversationScope.hotel" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-requestParameters">
|
||||
@@ -164,8 +164,8 @@
|
||||
<para>
|
||||
Use <code>requestParameters</code> to access a client request parameter:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<set name="requestScope.hotelId" value="requestParameters.id" type="long" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<set name="requestScope.hotelId" value="requestParameters.id" type="long" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-currentEvent">
|
||||
@@ -173,8 +173,8 @@
|
||||
<para>
|
||||
Use <code>currentEvent</code> to access attributes of the current <code>Event</code>:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<evaluate expression="booking.guests.add(currentEvent.guest)" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<evaluate expression="booking.guests.add(currentEvent.guest)" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-currentUser">
|
||||
@@ -182,9 +182,9 @@
|
||||
<para>
|
||||
Use <code>currentUser</code> to access the authenticated <code>Principal</code>:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)"
|
||||
result="flowScope.booking" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)"
|
||||
result="flowScope.booking" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-messageContext">
|
||||
@@ -193,8 +193,8 @@
|
||||
Use <code>messageContext</code> to access a context for retrieving and creating flow execution messages, including error and success messages.
|
||||
See the <code>MessageContext</code> Javadocs for more information.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<evaluate expression="bookingValidator.validate(booking, messageContext)" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<evaluate expression="bookingValidator.validate(booking, messageContext)" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="el-variable-requestContext">
|
||||
@@ -223,9 +223,9 @@
|
||||
Use <code>externalContext</code> to access the client environment, including user session attributes.
|
||||
See the <code>ExternalContext</code> API JavaDocs for more information.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<evaluate expression="searchService.suggestHotels(externalContext.sessionMap.userProfile)"
|
||||
result="viewScope.hotels" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<evaluate expression="searchService.suggestHotels(externalContext.sessionMap.userProfile)"
|
||||
result="viewScope.hotels" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
@@ -235,15 +235,15 @@
|
||||
When assigning a variable in one of the flow scopes, referencing that scope is required.
|
||||
For example:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<set name="requestScope.hotelId" value="requestParameters.id" type="long" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<set name="requestScope.hotelId" value="requestParameters.id" type="long" />]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
When simply accessing a variable in one of the scopes, referencing the scope is optional.
|
||||
For example:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<evaluate expression="entityManager.persist(booking)" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<evaluate expression="entityManager.persist(booking)" />]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
If no scope is specified, like in the use of <code>booking</code> above, a scope searching algorithm will be employed.
|
||||
|
||||
@@ -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.
|
||||
</para>
|
||||
<table>
|
||||
<table id="field-mappings-table">
|
||||
<title>Mappings</title>
|
||||
<tgroup cols="5">
|
||||
<colspec colname="1.0-element" colwidth="*"/>
|
||||
|
||||
@@ -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.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<flow parent="common-transitions, common-states">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<flow parent="common-transitions, common-states">]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="flow-inheritance-level-state">
|
||||
@@ -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.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="child-state" parent="parent-flow#parent-view-state">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="child-state" parent="parent-flow#parent-view-state">]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
@@ -67,8 +67,8 @@
|
||||
In order to protect these flow from running, they can be marked as <code>abstract</code>.
|
||||
If an abstract flow attempts to run, a <code>FlowBuilderException</code> will be thrown.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<flow abstract="true">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<flow abstract="true">]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1 id="flow-inheritance-algorithm">
|
||||
|
||||
@@ -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.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<secured attributes="ROLE_USER" />
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<secured attributes="ROLE_USER" />]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<secured attributes="ROLE_USER, ROLE_ANONYMOUS" match="any" />
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<secured attributes="ROLE_USER, ROLE_ANONYMOUS" match="any" />]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
This attribute is optional.
|
||||
@@ -121,33 +121,33 @@
|
||||
The Spring configuration defines <code>http</code> specifics (such as protected URLs and login/logout mechanics) and the <code>authentication-provider</code>.
|
||||
For the sample applications, a local authentication provider is configured.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<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" />
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<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:form-login login-page="/spring/login"
|
||||
login-url="/spring/login-process"
|
||||
default-target-url="/spring/main"
|
||||
authentication-failure-url="/spring/login?login_error=1" />
|
||||
authentication-failure-url="/spring/login?login_error=1" />
|
||||
|
||||
<security:logout logout-url="/spring/logout" logout-success-url="/spring/logout-success" />
|
||||
</security:http>
|
||||
<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>
|
||||
<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>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="flow-security-configuration-web">
|
||||
@@ -157,16 +157,16 @@
|
||||
This filter will listen for login/logout requests and process them accordingly.
|
||||
It will also catch <code>AccesDeniedException</code>s and redirect the user to the login page.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<filter>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<filter>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
<filter-mapping>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
@@ -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:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/webflow-config
|
||||
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
|
||||
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
|
||||
|
||||
<!-- Setup Web Flow here -->
|
||||
<!-- Setup Web Flow here -->
|
||||
|
||||
</beans>
|
||||
</beans>]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1 id="system-config-basic">
|
||||
@@ -38,10 +38,10 @@
|
||||
<para>
|
||||
Register your flows in a <code>FlowRegistry</code>:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<webflow:flow-registry id="flowRegistry">
|
||||
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
|
||||
</webflow:flow-registry>
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<webflow:flow-registry id="flowRegistry">
|
||||
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
|
||||
</webflow:flow-registry>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="basic-setup-flow-executor">
|
||||
@@ -49,8 +49,8 @@
|
||||
<para>
|
||||
Deploy a FlowExecutor, the central service for executing flows:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<para>
|
||||
@@ -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.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
|
||||
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
|
||||
</webflow:flow-registry>
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<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" />
|
||||
<webflow:flow-builder-services id="flowBuilderServices" />]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
The configurable services are the <code>conversion-service</code>, <code>formatter-registry</code>, <code>expression-parser</code>, and <code>view-factory-creator</code>.
|
||||
These services are configured by referencing custom beans you define. For example:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<webflow:flow-builder-services id="flowBuilderServices"
|
||||
conversion-service="conversionService"
|
||||
formatter-registry="formatterRegistry"
|
||||
expression-parser="expressionParser"
|
||||
view-factory-creator="viewFactoryCreator"/>
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<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="..." />
|
||||
<bean id="conversionService" class="..." />
|
||||
<bean id="formatterRegistry" class="..." />
|
||||
<bean id="expressionParser" class="..." />
|
||||
<bean id="viewFactoryCreator" class="..." />]]>
|
||||
</programlisting>
|
||||
<sect3 id="builder-service-conversion">
|
||||
<title>conversion-service</title>
|
||||
@@ -126,16 +126,16 @@
|
||||
Use the <code>parent</code> 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.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<!-- my-system-config.xml -->
|
||||
<webflow:flow-registry id="flowRegistry" parent="sharedFlowRegistry">
|
||||
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
|
||||
</webflow:flow-registry>
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<!-- 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>
|
||||
<!-- shared-config.xml -->
|
||||
<webflow:flow-registry id="sharedFlowRegistry">
|
||||
<-- Global flows shared by several applications -->
|
||||
</webflow:flow-registry>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="flow-registry-location">
|
||||
@@ -144,8 +144,8 @@
|
||||
Use the <code>location</code> 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.
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="flow-registry-location-id">
|
||||
@@ -153,8 +153,8 @@
|
||||
<para>
|
||||
Specify an id to assign a custom registry identifier to a flow:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" id="bookHotel" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" id="bookHotel" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="flow-registry-location-attributes">
|
||||
@@ -162,13 +162,13 @@
|
||||
<para>
|
||||
Use the <code>flow-definition-attributes</code> element to assign custom meta-attributes to a registered flow:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<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>
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<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>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="flow-registry-patterns">
|
||||
@@ -176,8 +176,8 @@
|
||||
<para>
|
||||
Use the <code>flow-location-patterns</code> element to register flows that match a specific resource location pattern:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<webflow:flow-location-pattern value="/WEB-INF/flows/**/*-flow.xml" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<webflow:flow-location-pattern value="/WEB-INF/flows/**/*-flow.xml" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
@@ -188,17 +188,17 @@
|
||||
<para>
|
||||
Use the <code>flow-execution-listeners</code> element to register listeners that observe the lifecycle of flow executions:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<flow-execution-listeners>
|
||||
<listener ref="securityListener"/>
|
||||
<listener ref="persistenceListener"/>
|
||||
</flow-execution-listeners>
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<flow-execution-listeners>
|
||||
<listener ref="securityListener"/>
|
||||
<listener ref="persistenceListener"/>
|
||||
</flow-execution-listeners>]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
You may also configure a listener to observe only certain flows:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<listener ref="securityListener" criteria="securedFlow1,securedFlow2"/>
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<listener ref="securityListener" criteria="securedFlow1,securedFlow2"/>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="tuning-flow-execution-repository">
|
||||
@@ -206,8 +206,8 @@
|
||||
<para>
|
||||
Use the <code>flow-execution-repository</code> element to tune flow execution persistence settings:
|
||||
</para>
|
||||
<programlisting type="xml">
|
||||
<flow-execution-repository max-conversations="5" max-snapshots="30" />
|
||||
<programlisting type="xml"><![CDATA[
|
||||
<flow-execution-repository max-conversations="5" max-snapshots="30" />]]>
|
||||
</programlisting>
|
||||
<sect3 id="repository-max-conversations">
|
||||
<title>max-conversations</title>
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
<para>
|
||||
To test the execution of a XML-based flow definition, extend <code>AbstractXmlFlowExecutionTests</code>:
|
||||
</para>
|
||||
<programlisting language="java">
|
||||
<programlisting language="java"><![CDATA[
|
||||
public class BookingFlowExecutionTests extends AbstractXmlFlowExecutionTests {
|
||||
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1 id="override-getResource">
|
||||
@@ -23,11 +23,11 @@ public class BookingFlowExecutionTests extends AbstractXmlFlowExecutionTests {
|
||||
<para>
|
||||
At a minimum, you must override <code>getResource(FlowDefinitionResourceFactory)</code> to return the path to the flow you wish to test:
|
||||
</para>
|
||||
<programlisting language="java">
|
||||
<programlisting language="java"><![CDATA[
|
||||
@Override
|
||||
protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resourceFactory) {
|
||||
return resourceFactory.createFileResource("src/main/webapp/WEB-INF/flows/booking/booking.xml");
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1 id="override-configureFlowBuilderContext">
|
||||
@@ -36,11 +36,11 @@ protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resou
|
||||
If your flow has dependencies on externally managed services,
|
||||
also override <code>configureFlowBuilderContext(MockFlowBuilderContext)</code> to register stubs or mocks of those services:
|
||||
</para>
|
||||
<programlisting language="java">
|
||||
<programlisting language="java"><![CDATA[
|
||||
@Override
|
||||
protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
|
||||
builderContext.registerBean("bookingService", new StubBookingService());
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1 id="testing-flowstartup">
|
||||
@@ -48,7 +48,7 @@ protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext
|
||||
<para>
|
||||
Have your first test exercise the startup of your flow:
|
||||
</para>
|
||||
<programlisting language="java">
|
||||
<programlisting language="java"><![CDATA[
|
||||
public void testStartBookingFlow() {
|
||||
|
||||
Booking booking = createTestBooking();
|
||||
@@ -61,7 +61,7 @@ public void testStartBookingFlow() {
|
||||
|
||||
assertCurrentStateEquals("enterBookingDetails");
|
||||
assertTrue(getRequiredFlowAttribute("booking") instanceof Booking);
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
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 <code>setCurrentState(String)</code> method to jump to the flow state where you wish to begin your test.
|
||||
</para>
|
||||
<programlisting>
|
||||
<programlisting><![CDATA[
|
||||
public void testEnterBookingDetails_Proceed() {
|
||||
|
||||
setCurrentState("enterBookingDetails");
|
||||
@@ -86,7 +86,7 @@ public void testEnterBookingDetails_Proceed() {
|
||||
resumeFlow(context);
|
||||
|
||||
assertCurrentStateEquals("reviewBooking");
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1 id="testing-mockingsubflows">
|
||||
@@ -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.
|
||||
</para>
|
||||
<programlisting language="java">
|
||||
<programlisting language="java"><![CDATA[
|
||||
public void testBookHotel() {
|
||||
|
||||
setCurrentState("reviewHotel");
|
||||
@@ -127,7 +127,7 @@ public Flow createMockBookingSubflow() {
|
||||
});
|
||||
// immediately return the bookingConfirmed outcome so the caller can respond
|
||||
new EndState(mockBookingFlow, "bookingConfirmed");
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
</chapter>
|
||||
@@ -12,10 +12,10 @@
|
||||
<para>
|
||||
Use the <code>view-state</code> element to define a step of the flow that renders a view and waits for a user event to resume:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="enterBookingDetails" >
|
||||
<transition on="submit" to="reviewBooking" />
|
||||
</view-state>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="enterBookingDetails">
|
||||
<transition on="submit" to="reviewBooking" />
|
||||
</view-state>]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
By convention, a view-state maps its id to a view template in the directory where the flow is located.
|
||||
@@ -47,8 +47,8 @@
|
||||
<para>
|
||||
The view id may be a relative path to view resource in the flow's working directory:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="enterBookingDetails" view="bookingDetails.xhtml">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="enterBookingDetails" view="bookingDetails.xhtml">]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="view-explicit-absolute">
|
||||
@@ -56,8 +56,8 @@
|
||||
<para>
|
||||
The view id may be a absolute path to a view resource in the webapp root directory:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="enterBookingDetails" view="/WEB-INF/hotels/booking/bookingDetails.xhtml">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="enterBookingDetails" view="/WEB-INF/hotels/booking/bookingDetails.xhtml">]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="view-explicit-logical">
|
||||
@@ -65,8 +65,8 @@
|
||||
<para>
|
||||
With some view frameworks, such as Spring MVC's view framework, the view id may also be a logical identifier resolved by the framework:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="enterBookingDetails" view="bookingDetails">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="enterBookingDetails" view="bookingDetails">]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
See the Spring MVC integration section for more information on how to integrate with the MVC <code>ViewResolver</code> infrastructure.
|
||||
@@ -87,8 +87,8 @@
|
||||
Use the <code>var</code> tag to declare a view variable.
|
||||
Like a flow variable, any @Autowired references are automatically restored when the view state resumes.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<var name="searchCriteria" class="com.mycompany.myapp.hotels.SearchCriteria" />
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<var name="searchCriteria" class="com.mycompany.myapp.hotels.SearchCriteria" />]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="view-scope-actions">
|
||||
@@ -96,11 +96,10 @@
|
||||
<para>
|
||||
Use the <code>on-render</code> tag to assign a variable from an action result before the view renders:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<on-render>
|
||||
<evaluate expression="bookingService.findHotels(searchCriteria)"
|
||||
result="viewScope.hotels" result-type="dataModel" />
|
||||
</on-render>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<on-render>
|
||||
<evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
|
||||
</on-render>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="view-scope-ajax">
|
||||
@@ -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.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<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>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="searchResults">
|
||||
<on-render>
|
||||
<evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
|
||||
</on-render>
|
||||
<transition on="next">
|
||||
<evaluate expression="searchCriteria.nextPage()" />
|
||||
<render fragments="searchResultsFragment" />
|
||||
</transition>
|
||||
<transition on="previous">
|
||||
<evaluate expression="searchCriteria.previousPage()" />
|
||||
<render fragments="searchResultsFragment" />
|
||||
</transition>
|
||||
</view-state>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
@@ -135,11 +133,10 @@
|
||||
Use the <code>on-render</code> 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.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<on-render>
|
||||
<evaluate expression="bookingService.findHotels(searchCriteria)"
|
||||
result="viewScope.hotels" result-type="dataModel" />
|
||||
</on-render>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<on-render>
|
||||
<evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
|
||||
</on-render>]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1 id="view-model">
|
||||
@@ -149,8 +146,8 @@
|
||||
This attribute is typically used with views that render data controls, such as forms.
|
||||
The following example declares the <code>enterBookingDetails</code> state manipulates the <code>booking</code> model:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="enterBookingDetails" model="booking">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="enterBookingDetails" model="booking">]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
The model may be in any accessible scope, such as <code>flowScope</code> or <code>viewScope</code>.
|
||||
@@ -175,11 +172,11 @@
|
||||
<para>
|
||||
Use the <code>bind</code> attribute to suppress model binding and validation for particular view events.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="enterBookingDetails">
|
||||
<transition on="proceed" to="reviewBooking">
|
||||
<transition on="cancel" to="bookingCancelled" bind="false" />
|
||||
</view-state>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="enterBookingDetails">
|
||||
<transition on="proceed" to="reviewBooking">
|
||||
<transition on="cancel" to="bookingCancelled" bind="false" />
|
||||
</view-state>]]>
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1 id="view-validate">
|
||||
@@ -197,11 +194,11 @@
|
||||
<title>Implementing a model validate method</title>
|
||||
<para>
|
||||
The first way is to define a validate method on the model object class.
|
||||
To do this, create a public method with the name <code>validate<state></code>, where <code>state</code> is the id of the view-state.
|
||||
To do this, create a public method with the name <code>validate</code>, where <code>state</code> is the id of the view-state.
|
||||
The method must declare a <code>MessageContext</code> parameter for recording validation error messages.
|
||||
For example:
|
||||
</para>
|
||||
<programlisting language="java">
|
||||
<programlisting language="java"><![CDATA[
|
||||
public void validateEnterBookingDetails(MessageContext context) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (checkinDate.before(today())) {
|
||||
@@ -211,18 +208,18 @@ public void validateEnterBookingDetails(MessageContext context) {
|
||||
context.addMessage(new MessageBuilder().error().source("checkoutDate").defaultText(
|
||||
"Check out date must be later than check in date").build());
|
||||
}
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
<sect3 id="view-validation=programmatic-validator">
|
||||
<title>Implementing a Validator</title>
|
||||
<para>
|
||||
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 <code>validate<state></code>, where <code>state</code> is the id of the view-state.
|
||||
To do this, create a class that defines a public method with the name <code>validate</code>, where <code>state</code> is the id of the view-state.
|
||||
The method must declare a <code>Object</code> parameter to accept your model object, and a <code>MessageContext</code> parameter for recording validation error messages.
|
||||
For example:
|
||||
</para>
|
||||
<programlisting language="java">
|
||||
<programlisting language="java"><![CDATA[
|
||||
public class BookingValidator {
|
||||
public void validateEnterBookingDetails(Object object, MessageContext context) {
|
||||
Booking booking = (Booking) object;
|
||||
@@ -234,7 +231,7 @@ public class BookingValidator {
|
||||
"Check out date must be later than check in date").build());
|
||||
}
|
||||
}
|
||||
}
|
||||
}]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
A Validator can also accept a Spring MVC <code>Errors</code> object, which is required for invoking existing Spring Validators.
|
||||
@@ -247,10 +244,10 @@ public class BookingValidator {
|
||||
<para>
|
||||
From a view-state, transitions without targets can also be defined. Such transitions are called "event handlers":
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<transition on="event">
|
||||
<-- Handle event -->
|
||||
</transition>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<transition on="event">
|
||||
<-- Handle event -->
|
||||
</transition>]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
These event handlers do not change the state of the flow.
|
||||
@@ -261,11 +258,11 @@ public class BookingValidator {
|
||||
<para>
|
||||
Use the <code>render</code> element to request partial re-rendering of a view after handling an event:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<transition on="next">
|
||||
<evaluate expression="searchCriteria.nextPage()" />
|
||||
<render fragments="searchResultsFragment" />
|
||||
</transition>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<transition on="next">
|
||||
<evaluate expression="searchCriteria.nextPage()" />
|
||||
<render fragments="searchResultsFragment" />
|
||||
</transition>]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
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 <code>global-transitions</code> 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.
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<global-transitions>
|
||||
<transition on="login"> to="login">
|
||||
<transition on="logout"> to="logout">
|
||||
</global-transitions>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<global-transitions>
|
||||
<transition on="login"> to="login">
|
||||
<transition on="logout"> to="logout">
|
||||
</global-transitions>]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
@@ -300,7 +297,7 @@ public class BookingValidator {
|
||||
</para>
|
||||
<sect2 id="plain-text-message">
|
||||
<title>Adding plain text messages</title>
|
||||
<programlisting type="java">
|
||||
<programlisting type="java"><![CDATA[
|
||||
MessageContext context = ...
|
||||
MessageBuilder builder = new MessageBuilder();
|
||||
context.addMessage(builder.error().source("checkinDate")
|
||||
@@ -309,19 +306,19 @@ context.addMessage(builder.warn().source("smoking")
|
||||
.defaultText("Smoking is bad for your health").build());
|
||||
context.addMessage(builder.info()
|
||||
.defaultText("We have processed your reservation - thank you and enjoy your stay")
|
||||
.build());
|
||||
.build());]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="plain-text-message-intl">
|
||||
<title>Adding internationalized messages</title>
|
||||
<programlisting type="java">
|
||||
<programlisting type="java"><![CDATA[
|
||||
MessageContext context = ...
|
||||
MessageBuilder builder = new MessageBuilder();
|
||||
context.addMessage(builder.error().source("checkinDate").code("checkinDate.notFuture")
|
||||
.build());
|
||||
context.addMessage(builder.warn().source("smoking").code("notHealthy")
|
||||
.resolvableArg("smoking").build());
|
||||
context.addMessage(builder.info().code("reservationConfirmation").build());
|
||||
context.addMessage(builder.info().code("reservationConfirmation").build());]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="message-bundles">
|
||||
@@ -331,11 +328,11 @@ context.addMessage(builder.info().code("reservationConfirmation").build());
|
||||
To create a flow-specific message bundle, simply define <code>messages.properties</code> file(s) in your flow's directory.
|
||||
Create a default <code>messages.properties</code> file and a .properties file for each additional <code>Locale</code> you need to support.
|
||||
</para>
|
||||
<programlisting type="properties">
|
||||
<programlisting type="properties"><![CDATA[
|
||||
#messages.properties
|
||||
checkinDate=Check in date must be a future date
|
||||
notHealthy={0} is bad for your health
|
||||
reservationConfirmation=We have processed your reservation - thank you and enjoy your stay
|
||||
reservationConfirmation=We have processed your reservation - thank you and enjoy your stay]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
@@ -344,8 +341,8 @@ reservationConfirmation=We have processed your reservation - thank you and enjoy
|
||||
<para>
|
||||
Use the <code>popup</code> attribute to render a view in a modal popup dialog:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">]]>
|
||||
</programlisting>
|
||||
<para>
|
||||
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
|
||||
<para>
|
||||
Set the history attribute to <code>discard</code> to prevent backtracking to a view:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="changeSearchCriteria" history="discard">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="changeSearchCriteria" history="discard">]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="history-invalidate">
|
||||
@@ -372,8 +369,8 @@ reservationConfirmation=We have processed your reservation - thank you and enjoy
|
||||
<para>
|
||||
Set the history attribute to <code>invalidate</code> to prevent backtracking to a view as well all previously displayed views:
|
||||
</para>
|
||||
<programlisting language="xml">
|
||||
<view-state id="changeSearchCriteria" history="invalidate">
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<view-state id="changeSearchCriteria" history="invalidate">]]>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
Reference in New Issue
Block a user