polish
This commit is contained in:
@@ -3,8 +3,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Getting Started with Spring Web Flow: Creating Your First Web Flow</title>
|
||||
<link rel="stylesheet" href="<c:url value="/resources/dijit/themes/tundra/tundra.css"/>" type="text/css" />
|
||||
<link rel="stylesheet" href="<c:url value="/resources/styles/tutorial.css"/>" type="text/css" />
|
||||
<script type="text/javascript" src="<c:url value="/resources/dojo/dojo.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/resources/spring/Spring.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/resources/spring/Spring-Dojo.js"/>"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body class="tundra">
|
||||
<h1>
|
||||
Creating Your First Web Flow
|
||||
</h1>
|
||||
@@ -28,185 +33,211 @@
|
||||
<h2>
|
||||
Step-by-step instructions for creating your first flow using the Eclipse-based SpringSource Tool Suite IDE:
|
||||
</h2>
|
||||
<h3>Setup the project development environment</h3>
|
||||
<ol>
|
||||
<li>
|
||||
Download <a href="http://www.springsource.com/products/sts">SpringSource Tool Suite</a> (STS) and the latest <a href="http://www.springsource.org/download#webflow">Spring Web Flow 2.0.x release</a>.
|
||||
After downloading completes, extract both archives to your directory of choice.
|
||||
</li>
|
||||
<li>
|
||||
Open STS and access File -> Import... -> Existing Projects Into Workspace. Select Browse... and navigate to where you extracted the Spring Web Flow release.
|
||||
Select the spring-webflow-samples/getting-started-with-spring-webflow folder and import the project.
|
||||
</li>
|
||||
<li>
|
||||
After the project import, if you do not already have a servlet container such as Tomcat installed on your workstation you can uses STS to install an embedded Tomcat instance.
|
||||
To do this, select the SpringSource logo on the tool bar, access the Configuration tab, and select Create Server Instance.
|
||||
</li>
|
||||
<li>
|
||||
Next, right-click on the project in your Package Explorer view, and select Run On Server.
|
||||
Select the server runtime you wish to deploy to and finish to deploy the project.
|
||||
You should see the tutorial welcome page appear in the embedded web browser.
|
||||
Alternatively, you can access the application in an external browser such as Firefox at <a href="http://localhost:8080/getting-started-with-spring-webflow">http://localhost:8080/getting-started-with-spring-webflow</a>
|
||||
</li>
|
||||
</ol>
|
||||
<h3>Create your first helloworld flow</h3>
|
||||
<ol>
|
||||
<li>
|
||||
Once the application is running, create a new directory for your flow inside /src/main/webapp/WEB-INF; name the directory helloworld.
|
||||
Next, right-click on the directory and access New -> Spring Web Flow Definition.
|
||||
Enter the filename helloworld-flow.xml and finish.
|
||||
The flow definition will be generated for you with an initial view-state named start.
|
||||
</li>
|
||||
<li>
|
||||
Go ahead and create a start.jsp in your flow directory and paste in the following:
|
||||
<pre>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello world!</title>
|
||||
</head>
|
||||
<h1>
|
||||
Hello world!
|
||||
</h1>
|
||||
</html>
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
From the Servers view, restart your server, then startup your flow by accessing <a href="http://localhost:8080/getting-started-with-spring-webflow/app/helloworld">http://localhost:8080/getting-started-with-spring-webflow/app/helloworld</a>.
|
||||
You should see your Hello world! message display.
|
||||
Note you only have to restart your server when you add new flows to the system. When you change flows, changes will be refreshed automatically.
|
||||
</li>
|
||||
</ol>
|
||||
<h3>Add a navigation rule</h3>
|
||||
<ol>
|
||||
<li>
|
||||
Next, try transitioning your flow from one state to another to implement a navigation rule. In your helloworld flow, add the following transition to your start view-state:
|
||||
<pre>
|
||||
<transition on="submit" to="page2" />
|
||||
</pre>
|
||||
Then define your page2 view-state:
|
||||
<pre>
|
||||
<view-state id="page2">
|
||||
</view-state>
|
||||
</pre>
|
||||
And the corresponding page2.jsp:
|
||||
<pre>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello world!</title>
|
||||
</head>
|
||||
<h1>
|
||||
This is page 2!
|
||||
</h1>
|
||||
</html>
|
||||
</pre>
|
||||
Finally, create a button on your start.jsp that raises the submit event to trigger the state transition:
|
||||
<pre>
|
||||
<form method="post">
|
||||
<input type="submit" name="_eventId_submit" value="Submit" />
|
||||
</form>
|
||||
</pre>
|
||||
Click the button and you should be taken to page 2.
|
||||
</li>
|
||||
</ol>
|
||||
<h3>Add a dynamic navigation rule</h3>
|
||||
<p>
|
||||
Web flow excels at implementing dynamic navigation logic that takes a user through different paths based on what they enter or who they are.
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Try implementing a dynamic navigation rule by first adding a bound checkbox to your start.jsp.
|
||||
Do this by replacing the contents of your start.jsp with the following snippet:
|
||||
<pre>
|
||||
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello world!</title>
|
||||
</head>
|
||||
<h1>
|
||||
Hello world!
|
||||
</h1>
|
||||
<form:form method="post" modelAttribute="helloWorldForm">
|
||||
<form:checkbox path="selected" />
|
||||
<div id="section1" class="section">
|
||||
<h3>Setup your project</h3>
|
||||
<ol>
|
||||
<li>
|
||||
Download <a href="http://www.springsource.com/products/sts">SpringSource Tool Suite</a> (STS) and the latest <a href="http://www.springsource.org/download#webflow">Spring Web Flow 2.0.x release</a>.
|
||||
After downloading completes, extract both archives to your directory of choice.
|
||||
</li>
|
||||
<li>
|
||||
Open STS and access File -> Import... -> Existing Projects Into Workspace. Select Browse... and navigate to where you extracted the Spring Web Flow release.
|
||||
Select the <span class="file">spring-webflow-samples/getting-started-with-spring-webflow</span> folder and import the project.
|
||||
</li>
|
||||
<li>
|
||||
After the project import, if you do not already have a servlet container such as Tomcat installed on your workstation you can uses STS to install an embedded Tomcat instance.
|
||||
To do this, select the SpringSource logo on the tool bar, access the Configuration tab, and select Create Server Instance.
|
||||
</li>
|
||||
<li>
|
||||
Next, right-click on the project in your Package Explorer view, and select Run On Server.
|
||||
Select the server runtime you wish to deploy to and finish to deploy the project.
|
||||
You should see the tutorial welcome page appear in the embedded web browser.
|
||||
Alternatively, you can access the application in an external browser such as Firefox at <a href="http://localhost:8080/getting-started-with-spring-webflow">http://localhost:8080/getting-started-with-spring-webflow</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div id="section2" class="section">
|
||||
<h3>Create your first helloworld flow</h3>
|
||||
<ol>
|
||||
<li>
|
||||
Once the application is running, create a new directory for your flow inside <span class="file">/src/main/webapp/WEB-INF</span>; name the directory <span class="file">helloworld</span>.
|
||||
Next, right-click on the directory and access New -> Spring Web Flow Definition.
|
||||
Enter the filename <span class="file">helloworld-flow.xml</span> and finish.
|
||||
The flow definition will be generated for you with an initial view-state named start.
|
||||
</li>
|
||||
<li>
|
||||
Go ahead and create a <span class="file">start.jsp</span> in your flow directory and paste in the following:
|
||||
<pre>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello world!</title>
|
||||
</head>
|
||||
<h1>
|
||||
Hello world!
|
||||
</h1>
|
||||
</html>
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
From the Servers view, restart your server, then startup your flow by accessing <a href="http://localhost:8080/getting-started-with-spring-webflow/app/helloworld">http://localhost:8080/getting-started-with-spring-webflow/app/helloworld</a>.
|
||||
You should see your Hello world! message display.
|
||||
Note you only have to restart your server when you add new flows to the system. When you change flows, changes will be refreshed automatically.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div id="section3" class="section">
|
||||
<h3>Add a navigation rule</h3>
|
||||
<ol>
|
||||
<li>
|
||||
Next, try transitioning your flow from one state to another to implement a navigation rule. In your helloworld flow, add the following transition to your start view-state:
|
||||
<pre>
|
||||
<transition on="submit" to="page2" />
|
||||
</pre>
|
||||
Then define your page2 view-state:
|
||||
<pre>
|
||||
<view-state id="page2">
|
||||
</view-state>
|
||||
</pre>
|
||||
And the corresponding page2.jsp:
|
||||
<pre>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello world!</title>
|
||||
</head>
|
||||
<h1>
|
||||
This is page 2!
|
||||
</h1>
|
||||
</html>
|
||||
</pre>
|
||||
Finally, create a button on your <span class="file">start.jsp</span> that raises the submit event to trigger the state transition:
|
||||
<pre>
|
||||
<form method="post">
|
||||
<input type="submit" name="_eventId_submit" value="Submit" />
|
||||
</form:form>
|
||||
</html>
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
Next, create a HelloWorldForm class in the org.springframework.webflow.samples.helloworld package with the following code:
|
||||
<pre>
|
||||
package org.springframework.webflow.samples.helloworld;
|
||||
</form>
|
||||
</pre>
|
||||
Click the button and you should be taken to page 2.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div id="section4" class="section">
|
||||
<h3>Add a dynamic navigation rule</h3>
|
||||
<p>
|
||||
Web flow excels at implementing dynamic navigation logic that takes a user through different paths based on what they enter or who they are.
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Try implementing a dynamic navigation rule by first adding a bound checkbox to your <span class="file">start.jsp</span>.
|
||||
Do this by replacing its contents with the following snippet:
|
||||
<pre>
|
||||
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello world!</title>
|
||||
</head>
|
||||
<h1>
|
||||
Hello world!
|
||||
</h1>
|
||||
<form:form method="post" modelAttribute="helloWorldForm">
|
||||
<form:checkbox path="selected" />
|
||||
<input type="submit" name="_eventId_submit" value="Submit" />
|
||||
</form:form>
|
||||
</html>
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
Next, create a <span class="file">HelloWorldForm</span> class in the <span class="file">org.springframework.webflow.samples.helloworld</span> package with the following code:
|
||||
<pre>
|
||||
package org.springframework.webflow.samples.helloworld;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class HelloWorldForm implements Serializable {
|
||||
private boolean selected = true;
|
||||
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
this.selected = selected;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
At the top of your helloworld-flow, declare the HelloWorldForm as a flow variable:
|
||||
<pre>
|
||||
<var name="helloWorldForm" class="org.springframework.webflow.samples.helloworld.HelloWorldForm" />
|
||||
</pre>
|
||||
Then update your start view-state to use this variable as its data model, enabling automatic model binding and validation:
|
||||
<pre>
|
||||
<view-state id="start" model="helloWorldForm"> ...
|
||||
</pre>
|
||||
<p>
|
||||
Refresh your flow and the checkbox should render checked since the default value for the HelloWorldForm selected property is true.
|
||||
Uncheck the box and submit and go back in your browser and the unchecked status should be preserved.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Now insert a decision state that says if the checkbox is selected goto page2, else goto a new page3:
|
||||
<pre>
|
||||
<decision-state id="isSelected">
|
||||
<if test="helloWorldForm.selected" then="page2" else="page3" />
|
||||
</decision-state>
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class HelloWorldForm implements Serializable {
|
||||
private boolean selected = true;
|
||||
<view-state id="page2">
|
||||
</view-state>
|
||||
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
this.selected = selected;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
At the top of your helloworld-flow, declare the HelloWorldForm as a flow variable:
|
||||
<pre>
|
||||
<var name="helloWorldForm" class="org.springframework.webflow.samples.helloworld.HelloWorldForm" />
|
||||
</pre>
|
||||
Then update your start view-state to use this variable as its data model, enabling automatic model binding and validation:
|
||||
<pre>
|
||||
<view-state id="start" model="helloWorldForm"> ...
|
||||
</pre>
|
||||
<p>
|
||||
Refresh your flow and the checkbox should render checked since the default value for the HelloWorldForm.selected property is true.
|
||||
Uncheck the box and submit and go back in your browser and the unchecked status should be preserved.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Now insert a decision state that says if the checkbox is selected goto page2, else goto a new page3:
|
||||
<pre>
|
||||
<decision-state id="isSelected">
|
||||
<if test="helloWorldForm.selected" then="page2" else="page3" />
|
||||
</decision-state>
|
||||
|
||||
<view-state id="page2">
|
||||
</view-state>
|
||||
|
||||
<view-state id="page3">
|
||||
</view-state>
|
||||
</pre>
|
||||
Be sure to update your start view-state to transition to the isSelected decision state instead of page2 directly:
|
||||
<pre>
|
||||
<view-state id="start">
|
||||
<transition on="submit" to="isSelected" />
|
||||
</view-state>
|
||||
</pre>
|
||||
Click the Submit button with the checkbox selected and you should be taken to page2.
|
||||
Click the button with the checkbox de-selected and you should be taken to page3 (you'll need to create a JSP or you'll get a 404).
|
||||
</li>
|
||||
</ol>
|
||||
<h3>Finish your helloworld flow</h3>
|
||||
<ol>
|
||||
<li>
|
||||
Finish up your helloworld flow by adding another button on the start.jsp that ends the flow:
|
||||
<pre>
|
||||
<input type="submit" name="_eventId_finish" value="Finish" />
|
||||
</pre>
|
||||
In your start view-state, declare the finish transition:
|
||||
<pre>
|
||||
<transition on="finish" to="finished" />
|
||||
</pre>
|
||||
And finally define the end-state:
|
||||
<pre>
|
||||
<end-state id="finished" view="externalRedirect:welcome" />
|
||||
</pre>
|
||||
Click the Finish button and you should be taken back to the application welcome screen.
|
||||
</li>
|
||||
</ol>
|
||||
<a href="tutorial?execution=${flowExecutionKey}&_eventId=next">Next ></a>
|
||||
<view-state id="page3">
|
||||
</view-state>
|
||||
</pre>
|
||||
Be sure to update your start view-state to transition to the isSelected decision state instead of page2 directly:
|
||||
<pre>
|
||||
<view-state id="start">
|
||||
<transition on="submit" to="isSelected" />
|
||||
</view-state>
|
||||
</pre>
|
||||
Click the Submit button with the checkbox selected and you should be taken to page2.
|
||||
Click the button with the checkbox de-selected and you should be taken to page3 (you'll need to create a JSP or you'll get a 404).
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div id="section5" class="section">
|
||||
<h3>Finish your helloworld flow</h3>
|
||||
<ol>
|
||||
<li>
|
||||
Finish up your helloworld flow by adding another button on the <span class="file">start.jsp</span> that ends the flow:
|
||||
<pre>
|
||||
<input type="submit" name="_eventId_finish" value="Finish" />
|
||||
</pre>
|
||||
In your start view-state, declare the finish transition:
|
||||
<pre>
|
||||
<transition on="finish" to="finished" />
|
||||
</pre>
|
||||
And finally define the end-state:
|
||||
<pre>
|
||||
<end-state id="finished" view="externalRedirect:welcome" />
|
||||
</pre>
|
||||
Click the Finish button and you should be taken back to the application welcome screen.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div id="commandBar">
|
||||
<p>
|
||||
<a href="tutorial?execution=${flowExecutionKey}&_eventId=next">Next ></a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
dojo.query('.section > h3').forEach(function(titleElement){
|
||||
Spring.addDecoration(new Spring.ElementDecoration({
|
||||
elementId : titleElement.parentNode.id,
|
||||
widgetType : 'dijit.TitlePane',
|
||||
widgetAttrs : {
|
||||
title : titleElement.innerHTML,
|
||||
open : false
|
||||
}
|
||||
}));
|
||||
}).style('display','none');
|
||||
</script>
|
||||
</html>
|
||||
@@ -3,46 +3,59 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Getting Started with Spring Web Flow: Overview of the Spring Web Flow Project</title>
|
||||
<link rel="stylesheet" href="<c:url value="/resources/dijit/themes/tundra/tundra.css"/>" type="text/css" />
|
||||
<link rel="stylesheet" href="<c:url value="/resources/styles/tutorial.css"/>" type="text/css" />
|
||||
<script type="text/javascript" src="<c:url value="/resources/dojo/dojo.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/resources/spring/Spring.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/resources/spring/Spring-Dojo.js"/>"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body class="tundra">
|
||||
<h1>
|
||||
Overview of the Spring Web Flow Project
|
||||
</h1>
|
||||
<h2>
|
||||
What is Spring Web Flow?
|
||||
</h2>
|
||||
<p>
|
||||
Spring Web Flow is a framework for implementing stateful web controllers.
|
||||
It is a Spring Project and part of Spring's open-source Web Stack.
|
||||
</p>
|
||||
<h2>
|
||||
When do I use Web Flow?
|
||||
</h2>
|
||||
<p>
|
||||
Use Spring Web Flow when you need to implement a flow that guides your users through a series of screens to complete a business goal.
|
||||
Web Flow provides a <i>flow definition language</i> for authoring flows that define screen navigation rules.
|
||||
The framework also cares for managing conversational state and preventing duplicate transactions.
|
||||
</p>
|
||||
<h2>
|
||||
How does Web Flow relate to other Spring projects?
|
||||
</h2>
|
||||
<p>
|
||||
Spring Web Flow builds on the Spring Framework project, which includes the Spring MVC web framework.
|
||||
Concretely, Spring Web Flow plugs into Spring MVC as a Controller technology.
|
||||
A typical Spring-powered web application is implemented using a mix of annotated Spring MVC Controllers and web flows.
|
||||
In general, use @Controllers for implementing simple, single-request user interactions, and web flows for stateful, multi-step user interactions.
|
||||
</p>
|
||||
<p>
|
||||
A number of other Spring projects also integrate with Spring Web Flow.
|
||||
The Spring Faces project uses Spring Web Flow as the controller framework to support implementing Spring-powered web applications that use JavaServerFaces (JSF) as the view technology.
|
||||
Spring Web Flow also provides integration with Spring Security for securing web flows.
|
||||
</p>
|
||||
<p>
|
||||
How Spring Web Flow fits into Spring's layered, a-la-carte "Web Stack" is illustrated below:<br>
|
||||
<img src="<c:url value="/resources/images/tutorial/spring-web-stack.png" />" />
|
||||
</p>
|
||||
<p>
|
||||
<a href="tutorial?execution=${flowExecutionKey}&_eventId=next">Next ></a>
|
||||
</p>
|
||||
<div id="question1" class="question">
|
||||
<h2>
|
||||
What is Spring Web Flow?
|
||||
</h2>
|
||||
<p>
|
||||
Spring Web Flow is a framework for implementing stateful web controllers.
|
||||
It is a Spring Project and part of Spring's open-source Web Stack.
|
||||
</p>
|
||||
</div>
|
||||
<div id="question2" class="question">
|
||||
<h2>
|
||||
When do I use Web Flow?
|
||||
</h2>
|
||||
<p>
|
||||
Use Spring Web Flow when you need to implement a flow that guides your users through a series of screens to complete a business goal.
|
||||
Web Flow provides a high-level <i>flow definition language</i> for authoring flows that define screen navigation rules.
|
||||
The framework also cares for managing conversational state and preventing duplicate transactions.
|
||||
</p>
|
||||
</div>
|
||||
<div id="question3" class="question">
|
||||
<h2>
|
||||
How does Web Flow relate to other Spring projects?
|
||||
</h2>
|
||||
<p>
|
||||
Spring Web Flow builds on the Spring Framework project, which includes the Spring MVC web framework.
|
||||
Concretely, Spring Web Flow plugs into Spring MVC as a Controller technology.
|
||||
A typical Spring-powered web application is implemented using a mix of annotated Spring MVC Controllers and web flows.
|
||||
In general, use @Controllers for implementing simple, single-request user interactions, and web flows for stateful, multi-step user interactions.
|
||||
</p>
|
||||
<p>
|
||||
A number of other Spring projects also integrate with Spring Web Flow.
|
||||
The Spring Faces project uses Spring Web Flow as the controller framework to support implementing Spring-powered web applications that use JavaServerFaces (JSF) as the view technology.
|
||||
Spring Web Flow also provides integration with Spring Security for securing web flows.
|
||||
</p>
|
||||
<p>
|
||||
How Spring Web Flow fits into Spring's layered, a-la-carte "Web Stack" is illustrated below:<br>
|
||||
<img src="<c:url value="/resources/images/tutorial/spring-web-stack.png" />" />
|
||||
</p>
|
||||
</div>
|
||||
<div id="commandBar">
|
||||
<p>
|
||||
<a href="tutorial?execution=${flowExecutionKey}&_eventId=next">Next ></a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,8 +3,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Getting Started with Spring Web Flow: Setting up Web Flow in a Spring Web Application</title>
|
||||
<link rel="stylesheet" href="<c:url value="/resources/dijit/themes/tundra/tundra.css"/>" type="text/css" />
|
||||
<link rel="stylesheet" href="<c:url value="/resources/styles/tutorial.css"/>" type="text/css" />
|
||||
<script type="text/javascript" src="<c:url value="/resources/dojo/dojo.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/resources/spring/Spring.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/resources/spring/Spring-Dojo.js"/>"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body class="tundra">
|
||||
<h1>
|
||||
Setting up Web Flow in a Spring Web Application
|
||||
</h1>
|
||||
@@ -12,181 +17,203 @@
|
||||
This step covers the one-time configuration step of setting Web Flow up in a Spring web application.
|
||||
If you prefer to go right to implementing your first flow, you can <a href="tutorial?execution=${flowExecutionKey}&_eventId=next"">skip</a> this step.
|
||||
</p>
|
||||
<h2>
|
||||
What does the configuration of a typical Spring web application look like?
|
||||
</h2>
|
||||
<p>
|
||||
The configuration of every Spring web application starts in web.xml.
|
||||
There, a Spring MVC DispatcherServlet is defined to process all requests into the application.
|
||||
The DispatcherServlet itself is configured using a Spring container.
|
||||
It is responsible for routing web requests to the proper application controllers, such as your Spring MVC @Controllers and web flows.
|
||||
A typical DispatcherServlet declaration is shown below:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- The front controller of this Spring MVC application, responsible for handling all application requests -->
|
||||
<servlet>
|
||||
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>
|
||||
/WEB-INF/spring/*.xml
|
||||
</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!-- Map all /app requests to the DispatcherServlet for handling -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
|
||||
<url-pattern>/app/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
</pre>
|
||||
<p>
|
||||
This DispatcherServlet is configured to process requests into /app/*.
|
||||
The servlet's configuration is defined in the .xml files in /WEB-INF/spring.
|
||||
</p>
|
||||
<h2>
|
||||
How are Spring configuration files typically organized?
|
||||
</h2>
|
||||
<p>
|
||||
Inside /WEB-INF/spring, we generally recommend defining a configuration file for your application logic,
|
||||
and separate configuration files for framework infrastructure. For example:
|
||||
</p>
|
||||
<pre class="code">
|
||||
/webapp
|
||||
/WEB-INF
|
||||
/spring
|
||||
app-config.xml
|
||||
mvc-config.xml
|
||||
webflow-config.xml
|
||||
web.xml
|
||||
</pre>
|
||||
<p>
|
||||
The example above shows the configuration for a Spring web application spread across three files.
|
||||
The app-config.xml file configures your components that carry out application-specific controller, business, and data access logic.
|
||||
The mvc-config.xml file configures the Spring MVC framework infrastructure, including the properties of the DispatcherServlet.
|
||||
The webflow-config.xml file configures the Spring Web Flow infrastructure.
|
||||
</p>
|
||||
<p>
|
||||
We also generally recommend using annotations to configure your application components, and externalized XML to configure infrastructure.
|
||||
This is illustrated in app-config.xml by use of the component-scan directive to scan your classpath for application components to deploy:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Scans within the base package of the application for @Components to configure as beans -->
|
||||
<context:component-scan base-package="org.springframework.webflow.samples.gettingstarted" />
|
||||
</pre>
|
||||
<p>
|
||||
With this technique, your Spring configuration is setup once and you generally never have to update your configuration files again as new components are added to your application.
|
||||
</p>
|
||||
<h2>
|
||||
How do I plug-in Spring Web Flow?
|
||||
</h2>
|
||||
<p>
|
||||
In webflow-config.xml, first define a flow-registry to register the flows you have defined in your application:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Registers the web flows that can be executed -->
|
||||
<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF/">
|
||||
<webflow:flow-location-pattern value="**/*-flow.xml" />
|
||||
</webflow:flow-registry>
|
||||
</pre>
|
||||
<p>
|
||||
The example above scans /WEB-INF looking for -flow.xml files and registers them.
|
||||
</p>
|
||||
<p>
|
||||
Then, define a flow-executor that uses this registry to execute your flows:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Configures the engine that executes web flows in this application -->
|
||||
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry" />
|
||||
</pre>
|
||||
<p>
|
||||
Finally, in mvc-config.xml plug in adapters to hook the flow-executor into the Spring MVC DispatcherServlet request processing pipeline:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Maps requests to flows in the flowRegistry -->
|
||||
<bean id="flowMappings" class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
|
||||
<property name="order" value="0" />
|
||||
<property name="flowRegistry" ref="flowRegistry" />
|
||||
</bean>
|
||||
|
||||
<!-- Enables Spring Web Flow as a Spring MVC request handler -->
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
|
||||
<property name="flowExecutor" ref="flowExecutor" />
|
||||
</bean>
|
||||
</pre>
|
||||
<p>
|
||||
We also recommend you turn on development mode while developing so you never have to redeploy your application to test changes:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<webflow:flow-builder-services id="flowBuilderServices" development="true" />
|
||||
</pre>
|
||||
<h2>
|
||||
How do Spring MVC @Controllers and Web Flows co-exist in the same application?
|
||||
</h2>
|
||||
<p>
|
||||
A typical Spring web application consists of a mix of stateless MVC @Controllers and stateful web flows, which are two distinct types of handlers.
|
||||
When a web request comes in for a resource, the DispatcherServlet figures out which handler should be invoked.
|
||||
This is done by consulting an ordered chain of HandlerMapping objects configured in your mvc-config.xml.
|
||||
Generally, the first HandlerMapping consulted is the FlowHandlerMapping, which determines if the requested resource should be handled by a web flow.
|
||||
If no flow handler is found, the next HandlerMapping in the chain is queried.
|
||||
This is generally the DefaultAnnotationHandlerMapping, which consults explicit @RequestMapping rules defined inside annotated Spring MVC Controllers.
|
||||
</p>
|
||||
<p>
|
||||
Setting up the HandlerMapping chain is a one-time configuration step, and makes it easy to plug in different types of handlers and mapping strategies.
|
||||
A typical HandlerMapping chain for Spring web applications looks like:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Maps requests to flows in the flowRegistry; for example, a request for resource /hotels/booking maps to a flow with id "hotels/booking"
|
||||
If no flow is found with that id, Spring MVC proceeds to the next HandlerMapping (order=1 below). -->
|
||||
<bean id="flowMappings" class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
|
||||
<property name="order" value="0" />
|
||||
<property name="flowRegistry" ref="flowRegistry" />
|
||||
</bean>
|
||||
|
||||
<!-- Maps requests to @Controllers based on @RequestMapping("path") annotation values
|
||||
If no annotation-based path mapping is found, Spring MVC proceeds to the next HandlerMapping (order=2 below). -->
|
||||
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
|
||||
<property name="order" value="1" />
|
||||
</bean>
|
||||
</pre>
|
||||
<p>
|
||||
Once a request has been mapped to a handler object such as a @Controller of web flow, the DispatcherServlet uses the HandlerAdapter registered for that kind of handler to invoke it.
|
||||
This decouples the DispatcherServlet from specific handler implementations, which allows Spring MVC to support different controller technologies in an extensible manner.
|
||||
As a one-time configuration step, a typical Spring web application registers HandlerAdapters that know how to invoke @Controllers and web flows when they are mapped:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Enables annotated @Controllers; responsible for invoking an annotated POJO @Controller when one is mapped. -->
|
||||
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
|
||||
|
||||
<!-- Enables web flows; responsible for calling the Spring Web Flow system to execute a flow when one is mapped. -->
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
|
||||
<property name="flowExecutor" ref="flowExecutor" />
|
||||
</bean>
|
||||
</pre>
|
||||
<p>
|
||||
To illustrate a typical DispatcherServlet pipeline, the following graphic illustrates the sequence of events that happen in this application when the /tutorial resource is requested, which is handled by the web flow you are interacting with right now:<br>
|
||||
<img src="<c:url value="/resources/images/tutorial/dispatcher-servlet-flow-handler.png" />" />
|
||||
</p>
|
||||
<p>
|
||||
In this scenario, the FlowHandlerMapping returned the tutorial flow which was then invoked by the FlowHandlerAdapter.
|
||||
</p>
|
||||
<p>
|
||||
The following graphic shows the sequence in this application when the /welcome resource is requested, which is handled by the annotated WelcomeController:<br>
|
||||
<img src="<c:url value="/resources/images/tutorial/dispatcher-servlet-annotated-controller-handler.png" />" />
|
||||
</p>
|
||||
<p>
|
||||
In this scenario, the FlowHandlerMapping returned null because the /welcome resource was not mapped to a web flow.
|
||||
The DefaultAnnotationHandlerMapping was then queried and returned the WelcomeController, which was invoked by the AnnotationMethodHandlerAdapter.
|
||||
</p>
|
||||
<p>
|
||||
The main point to understand here is there is one-time configuration that enables full customization of the DispatcherServlet processing pipeline.
|
||||
Once this configuration is established, you simply create new controllers and web flows, and they get picked up and hooked into the pipeline automatically.
|
||||
No other configuration is required.
|
||||
</p>
|
||||
<p>
|
||||
<a href="tutorial?execution=${flowExecutionKey}&_eventId=next">Next ></a>
|
||||
</p>
|
||||
<div id="question1" class="question">
|
||||
<h2>
|
||||
What does the configuration of a typical Spring web application look like?
|
||||
</h2>
|
||||
<p>
|
||||
The configuration of every Spring web application starts in web.xml.
|
||||
There, a Spring MVC DispatcherServlet is defined to process all requests into the application.
|
||||
The DispatcherServlet itself is configured using a Spring container.
|
||||
It is responsible for routing web requests to the proper application controllers, such as your Spring MVC @Controllers and web flows.
|
||||
A typical DispatcherServlet declaration is shown below:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- The front controller of this Spring MVC application, responsible for handling all application requests -->
|
||||
<servlet>
|
||||
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>
|
||||
/WEB-INF/spring/*.xml
|
||||
</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!-- Map all /app requests to the DispatcherServlet for handling -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
|
||||
<url-pattern>/app/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
</pre>
|
||||
<p>
|
||||
This DispatcherServlet is configured to process requests into /app/*.
|
||||
The servlet's configuration is defined in the .xml files in /WEB-INF/spring.
|
||||
</p>
|
||||
</div>
|
||||
<div id="question2" class="question">
|
||||
<h2>
|
||||
How are Spring configuration files typically organized?
|
||||
</h2>
|
||||
<p>
|
||||
Inside /WEB-INF/spring, we generally recommend defining a configuration file for your application logic,
|
||||
and separate configuration files for framework infrastructure. For example:
|
||||
</p>
|
||||
<pre class="code">
|
||||
/webapp
|
||||
/WEB-INF
|
||||
/spring
|
||||
app-config.xml
|
||||
mvc-config.xml
|
||||
webflow-config.xml
|
||||
web.xml
|
||||
</pre>
|
||||
<p>
|
||||
The example above shows the configuration for a Spring web application spread across three files.
|
||||
The app-config.xml file configures your components that carry out application-specific controller, business, and data access logic.
|
||||
The mvc-config.xml file configures the Spring MVC framework infrastructure, including the properties of the DispatcherServlet.
|
||||
The webflow-config.xml file configures the Spring Web Flow infrastructure.
|
||||
</p>
|
||||
<p>
|
||||
We also generally recommend using annotations to configure your application components, and externalized XML to configure infrastructure.
|
||||
This is illustrated in app-config.xml by use of the component-scan directive to scan your classpath for application components to deploy:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Scans within the base package of the application for @Components to configure as beans -->
|
||||
<context:component-scan base-package="org.springframework.webflow.samples.gettingstarted" />
|
||||
</pre>
|
||||
<p>
|
||||
With this technique, your Spring configuration is setup once and you generally never have to update your configuration files again as new components are added to your application.
|
||||
</p>
|
||||
</div>
|
||||
<div id="question3" class="question">
|
||||
<h2>
|
||||
How do I plug-in Spring Web Flow?
|
||||
</h2>
|
||||
<p>
|
||||
In webflow-config.xml, first define a flow-registry to register the flows you have defined in your application:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Registers the web flows that can be executed -->
|
||||
<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF/">
|
||||
<webflow:flow-location-pattern value="**/*-flow.xml" />
|
||||
</webflow:flow-registry>
|
||||
</pre>
|
||||
<p>
|
||||
The example above scans /WEB-INF looking for -flow.xml files and registers them.
|
||||
</p>
|
||||
<p>
|
||||
Then, define a flow-executor that uses this registry to execute your flows:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Configures the engine that executes web flows in this application -->
|
||||
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry" />
|
||||
</pre>
|
||||
<p>
|
||||
Finally, in mvc-config.xml plug in adapters to hook the flow-executor into the Spring MVC DispatcherServlet request processing pipeline:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Maps requests to flows in the flowRegistry -->
|
||||
<bean id="flowMappings" class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
|
||||
<property name="order" value="0" />
|
||||
<property name="flowRegistry" ref="flowRegistry" />
|
||||
</bean>
|
||||
|
||||
<!-- Enables Spring Web Flow as a Spring MVC request handler -->
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
|
||||
<property name="flowExecutor" ref="flowExecutor" />
|
||||
</bean>
|
||||
</pre>
|
||||
<p>
|
||||
We also recommend you turn on development mode while developing so you never have to redeploy your application to test changes:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<webflow:flow-builder-services id="flowBuilderServices" development="true" />
|
||||
</pre>
|
||||
</div>
|
||||
<div id="question4" class="question">
|
||||
<h2>
|
||||
How do Spring MVC @Controllers and Web Flows co-exist in the same application?
|
||||
</h2>
|
||||
<p>
|
||||
A typical Spring web application consists of a mix of stateless MVC @Controllers and stateful web flows, which are two distinct types of handlers.
|
||||
When a web request comes in for a resource, the DispatcherServlet figures out which handler should be invoked.
|
||||
This is done by consulting an ordered chain of HandlerMapping objects configured in your mvc-config.xml.
|
||||
Generally, the first HandlerMapping consulted is the FlowHandlerMapping, which determines if the requested resource should be handled by a web flow.
|
||||
If no flow handler is found, the next HandlerMapping in the chain is queried.
|
||||
This is generally the DefaultAnnotationHandlerMapping, which consults explicit @RequestMapping rules defined inside annotated Spring MVC Controllers.
|
||||
</p>
|
||||
<p>
|
||||
Setting up the HandlerMapping chain is a one-time configuration step, and makes it easy to plug in different types of handlers and mapping strategies.
|
||||
A typical HandlerMapping chain for Spring web applications looks like:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Maps requests to flows in the flowRegistry; for example, a request for resource /hotels/booking maps to a flow with id "hotels/booking"
|
||||
If no flow is found with that id, Spring MVC proceeds to the next HandlerMapping (order=1 below). -->
|
||||
<bean id="flowMappings" class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
|
||||
<property name="order" value="0" />
|
||||
<property name="flowRegistry" ref="flowRegistry" />
|
||||
</bean>
|
||||
|
||||
<!-- Maps requests to @Controllers based on @RequestMapping("path") annotation values
|
||||
If no annotation-based path mapping is found, Spring MVC proceeds to the next HandlerMapping (order=2 below). -->
|
||||
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
|
||||
<property name="order" value="1" />
|
||||
</bean>
|
||||
</pre>
|
||||
<p>
|
||||
Once a request has been mapped to a handler object such as a @Controller of web flow, the DispatcherServlet uses the HandlerAdapter registered for that kind of handler to invoke it.
|
||||
This decouples the DispatcherServlet from specific handler implementations, which allows Spring MVC to support different controller technologies in an extensible manner.
|
||||
As a one-time configuration step, a typical Spring web application registers HandlerAdapters that know how to invoke @Controllers and web flows when they are mapped:
|
||||
</p>
|
||||
<pre class="code">
|
||||
<!-- Enables annotated @Controllers; responsible for invoking an annotated POJO @Controller when one is mapped. -->
|
||||
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
|
||||
|
||||
<!-- Enables web flows; responsible for calling the Spring Web Flow system to execute a flow when one is mapped. -->
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
|
||||
<property name="flowExecutor" ref="flowExecutor" />
|
||||
</bean>
|
||||
</pre>
|
||||
<p>
|
||||
To illustrate a typical DispatcherServlet pipeline, the following graphic illustrates the sequence of events that happen in this application when the /tutorial resource is requested, which is handled by the web flow you are interacting with right now:<br>
|
||||
<img src="<c:url value="/resources/images/tutorial/dispatcher-servlet-flow-handler.png" />" />
|
||||
</p>
|
||||
<p>
|
||||
In this scenario, the FlowHandlerMapping returned the tutorial flow which was then invoked by the FlowHandlerAdapter.
|
||||
</p>
|
||||
<p>
|
||||
The following graphic shows the sequence in this application when the /welcome resource is requested, which is handled by the annotated WelcomeController:<br>
|
||||
<img src="<c:url value="/resources/images/tutorial/dispatcher-servlet-annotated-controller-handler.png" />" />
|
||||
</p>
|
||||
<p>
|
||||
In this scenario, the FlowHandlerMapping returned null because the /welcome resource was not mapped to a web flow.
|
||||
The DefaultAnnotationHandlerMapping was then queried and returned the WelcomeController, which was invoked by the AnnotationMethodHandlerAdapter.
|
||||
</p>
|
||||
<p>
|
||||
The main point to understand here is there is one-time configuration that enables full customization of the DispatcherServlet processing pipeline.
|
||||
Once this configuration is established, you simply create new controllers and web flows, and they get picked up and hooked into the pipeline automatically.
|
||||
No other configuration is required.
|
||||
</p>
|
||||
</div>
|
||||
<div id="commandBar">
|
||||
<p>
|
||||
<a href="tutorial?execution=${flowExecutionKey}&_eventId=next">Next ></a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
dojo.query('.question > h2').forEach(function(titleElement){
|
||||
Spring.addDecoration(new Spring.ElementDecoration({
|
||||
elementId : titleElement.parentNode.id,
|
||||
widgetType : 'dijit.TitlePane',
|
||||
widgetAttrs : {
|
||||
title : titleElement.innerHTML,
|
||||
open : false
|
||||
}
|
||||
}));
|
||||
}).style('display','none');
|
||||
</script>
|
||||
</html>
|
||||
@@ -3,8 +3,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Getting Started with Spring Web Flow: Where To Go From Here</title>
|
||||
<link rel="stylesheet" href="<c:url value="/resources/dijit/themes/tundra/tundra.css"/>" type="text/css" />
|
||||
<link rel="stylesheet" href="<c:url value="/resources/styles/tutorial.css"/>" type="text/css" />
|
||||
<script type="text/javascript" src="<c:url value="/resources/dojo/dojo.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/resources/spring/Spring.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/resources/spring/Spring-Dojo.js"/>"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body class="tundra">
|
||||
<h1>
|
||||
Where To Go with From Here
|
||||
</h1>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
.dijitTitlePane + .dijitTitlePane {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.file {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
ol li {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
Reference in New Issue
Block a user