510 likes | 607 Views
Managing Web Conversations with Spring Web Flow. Keith Donald http://www.springframework.com keith@interface21.com. Agenda. History Motivation Positioning Architecture Walkthrough Issues and Solutions Conclusion Goals: Understand Spring’s position in the web framework space
E N D
Managing Web Conversationswith Spring Web Flow Keith Donald http://www.springframework.com keith@interface21.com
Agenda • History • Motivation • Positioning • Architecture • Walkthrough • Issues and Solutions • Conclusion • Goals: • Understand Spring’s position in the web framework space • See the value of Spring Web Flow (SWF) in action
2000 2003 2004 Fall 2005 Unified Spring Web Stack: Servlet MVC, Portlet MVC, Web Flow (SWF) Struts Spring MVC Ervacon Web Flows History – From Spring’s Perspective • Today, Struts is still the web framework leader in terms of existing application deployments • Despite well-known limitations • Despite many challengers • The pragmatic majority is still waiting for the next dominant paradigm to emerge
Spring’s Web Stack Motivation • To address the Struts pain points that are hurting our customers • Spring MVC provides a better architecture without a high level of paradigm shock • To meet customer demand in places where it is clear Struts does not provide a solution • Spring has embarked into new territory • With its customers charting the course • Extracting new “whole products” to form a complete web stack
Product Positioning • A unified web stack, offering a one stop shop for agile web application development • Respecting the existing Struts install base • Spring will continue to provide first class Struts support • Built from a set of modular components • That can be integrated with other technologies where customers demand • e.g. SWF is usable by JSF customers as a NavigationHandler
Spring Web Spring Web Stack Servlet MVC Portlet MVC Web Flow Remoting Spring Middleware Stack (IOC, AOP, TX, DAO, ORM, MGMT, JCA) Spring Clarity™ (Build, Test, Deploy) • Each product in the stack integrates a number of components • e.g.Spring MVC supports JSP, Freemarker, PDF, Jasper, and Excel views • Emerging web components include Valang for validation and DWR for AJAX
Market Expectations • The current fragmentation in the web framework market will subside • Consolidation will happen • “Spring Web” will be a major player in the post-shakeout, offering: • Maturity and synergy across the full stack • Low switching costs • Breakthrough technology • Professional support
Architecture • By example • Take a simple use case: • A wizard for a phone operator to use to sell items to customers • Characteristics: • An “application transaction” that spans several steps • Some steps solicit user input • Some steps are decision points • Some steps perform calculations • Navigation from step-to-step is controlled
How would you do this today with Struts? • Create a session-scoped ActionForm to hold the wizard form data • Define a JSP for each step • Define an Action for each step • Expose each Action at a request URL • Have the form rendered by the JSP submit to that URL • At the end, delegate to a business service to commit the transaction
Controller 1 updateForm Controller 2 Controller 3 What this looks like /step1.do storeForm HTTP Session page1 /step2.do page2 Business Service /lastStep.do processTx confirmationPage
Issues with this approach • Request centric: no concept of an ongoing conversation or flow • Brittle dependency on request URLs • Manual state management • Odd new window behavior • Proper back button behavior is difficult • “Loose” controlled navigation • Difficult to observe process lifecycle • Controller and command logic are coupled • Heavily tied to HTTP
Consequences • Many lines of custom code are written to address these issues • As an application grows more complex maintainability breaks down • Fundamentally, something is missing • Traditional approaches today lack a key abstraction: the Flow • A Flow is typically longer than a single request but shorter than a session • It is a conversation!
Flow Conversation Analogy Keith (Oslo, Norway) Friend: Hello? Keith: Hi Friend! Friend: Hi Keith! So, have you decided to just stay in Europe now? Keith: Life IS great here, huh? Keith: Gotta go, bye! Friend (Melbourne, Florida)
“Sell Item” FlowExecution What the SWF approach looks like start “sell Item” firstPage Flow Execution Storage store submit nextPage load submit confirmationPage
Significant architectural differences • One flow drives the entire conversation • When user input is required, the flow “pauses” and control returns to the client • Clients “signal” events to tell the flow what happened • The flow responds to events to decide what to do next • What to do next is fully encapsulated • Flows are modular “black boxes”
end Flow Execution State Transition Diagram Created Ending start Active Paused subflow spawned user input needed user event signaled Resuming
Question Q: How do you program the Flow? Q: How does it know what to do in response to user events? A: You create a Flow definition
Flow Definition Structure • A Flow definition serves as instructions to a finite state machine • It consists of a set of states that you define • Each state executes a polymorphic behavior when entered • View states solicit user input • Action states execute commands • Subflow states spawn child flows • End states terminate flows • Events you define drive state transitions
The “Sell Item” Flow Definition Enter Price and Item Count Enter Shipping Information submit start submit yes Select Item Category Is Shipping Required? Process Sale submit no View State Action State Show Cost Overview Decision State End State
Code Break! • The real “Sell Item” Flow Definition • Demo of the Flow Execution
Advantages • The logical flow is clearly defined, readable • Navigation rules are encapsulated in one place • No dependency on any request URLs • Navigation is strictly enforced • State management is automatic • Flow lifecycle is fully observable • Controller logic is clearly decoupled from command logic • The Flow is the controller, deciding what state to enter next • States execute arbitrary behavior when entered • HTTP independent • Flow definitions are extremely toolable
Walkthrough: Spring Air™ • The best way to learn is by example • The airline industry: • Trip booking system • This vertical slice must: • Obtain Trip Information • Suggest suitable itineraries • Assign seats • Collect passenger information • Book the trip!
Code Break! • The “Booking Agent” business façade • Subsystem boundary • The model context • The façade integration tests
Building the Booking Flow Definition • First select a FlowBuilder strategy • XML, Java-based, Custom • Perhaps with a supplemental drag ‘n drop tool • Then create the states of the flow • Define the behavior to happen when each state is entered • Define the supported transitions from one state to another • Transitions map the paths through the Flow
Code Break! • The Booking Flow Definition • The Booking Flow Action • The Action Unit Tests • The Flow Execution Integration Tests • The View Templates • Application Deployment Configuration
The Booking Flow Definition <webflow id="booking“ start-state=“displayTripForm"> <! – state definitions go here </webflow>
Rendering the Trip Form • Display the “trip form” so the user can tell the flow where she wants to go <view-state id="displayTripForm" view="tripForm"> <entry> <action bean="bookingFlowActions" method="setupForm"/> <action bean="formUtilityActions" method="setupDateChooser"/> </entry> <transition on="go" to="suggestItineraries"> <action bean="bookingFlowActions" method="bindAndValidate"/> </transition> </view-state>
Suggesting Trip Itineraries • Suggest the best itineraries: <action-state id="suggestItineraries"> <action bean=“bookingActions"/> <transition on="success“ to="displaySuggestedItineraries"/> </action-state> • Action states invoke methods on Actions when entered • Can also directly invoke methods on POJOs • Example: • Entering “suggestItineraries” invokes the “suggestItineraries” method on the action identified by “bookingActions”
The Booking Action Implementation public class BookingAction extends FormAction { private BookingAgent bookingAgent; private BookingAction(BookingAgent agent) { setFormObjectName("trip"); setFormObjectClass(Trip.class); this.bookingAgent = agent; } public Event suggestItinenaries(RequestContext context) { Trip trip = (Trip)context.getFlowScope().getAttribute("trip"); Collection<Itinerary> itineraries = bookingAgent.suggestItineraries(trip); context.getFlowScope().setAttribute("itineraries", itineraries); return success(); } // other action methods related to the booking process… public Event book(RequestContext context) { … } }
Selecting an Itinerary • Display the itineraries and let the customer select one: <view-state id="displaySuggestedItineraries" view="suggestedItineraries"> <transition on="startOver" to="cancel"/> <transition on="select" to=“recordSelectedItinerary"/> </view-state> <action-state id=“recordSelectedItinerary"> <action bean=“bookingActions"/> <transition on="success" to="isPassengerInfoRequired"/> </action-state> • The flow pauses while the view is displayed – user “think time” • It resumes in the same state on the next request to decide where to go next
Deciding where to go next • Is passenger information required? If so, enter it. If not, go straight to verification <action-state id=“isPassengerInfoRequired”> <transition on=“yes” to=“enterPassengerInformation”/> <transition on=“no” to=“displayReservationVerification”/> </action-state> • A logical decision point: “routing state” • A Decision State could have also been used
Entering Passenger Information • Spawn the “enter passenger information” process as a subflow, passing it the passenger ID if they have authenticated <subflow-state id="enterPassengerInformation" flow="passenger"> <attribute-mapper> <input value="${requestScope.passenger.id}“ as=“id”/> </attribute-mapper> <transition on="finish" to="displayReservationVerification"/> </subflow-state> • Note: the parent flow suspends while the subflow executes. When the subflow ends, the parent responds to its result.
Finalizing the Reservation • On verification, optionally choose seat assignments. Then book the reservation! <view-state id="displayReservationVerification" view="reservationVerification"> <transition on="startOver" to="cancel"/> <transition on="assignSeats" to="chooseSeatAssignments"/> <transition on="book" to="book"/> </view-state> <action-state id="book"> <action bean=“bookingFlowActions"/> <transition on="success" to="displayConfirmation"/> </action-state> <end-state id="displayConfirmation" view="reservationConfirmation"/> • The end state terminates the flow when entered • All flow resources are automatically cleaned up
Deploying the Flow <bean name="/springair.htm“ class="org.springframework.web.flow.mvc.FlowController"/> <bean id="booking“ class="org.springframework.web.flow.config.XmlFlowFactoryBean"> <property name="location“ value="classpath:/flows/booking.xml"/> </bean> • One Flow Controller can execute all flows for the application at a single request URL • The views parameterize the controller with flow launching information • Security would be at the flow level
Example: views launching flows • Using a form: <form method=“post” action=“springair.htm”/> <input type=“text” name=“src.airport”/> <input type=“text” name=“dest.airport”/> … <input type=“hidden” flowId=“booking”/> <input type=“submit” value=“Submit”/> </form> • Using an anchor: <a href="<c:url value="/springair.htm?_flowId=booking&src.airport=MLB& dest.airport=ATL"/>"> Launch Booking Flow </a>
Examples: views participating in flows • Using a form: <form method=“post” action=“springair.htm”/> <input type=“text” name=“firstName”/> <input type=“text” name=“lastName”/> … <input type=“hidden” name=“_flowExecutionId” value=“${flowExecutionId}”/> <input type=“submit” name=“_eventId_submit”/> </form> • Using an anchor: <a href="<c:url value="/springair.htm?_flowExecutionId=${flowExecutionId}& _eventId=submit&firstName=Keri&lastName=Donald/>“>Enter Passenger Information</a> • Each flow is assigned a unique identifier made available to the views for storage
Issues and Solutions • Browser navigation button use, flow storage and restoration • A stateful system brings challenges in a stateless environment • Continuations provide a solution • Server-side session-based storage • Client-side seralization using hidden form field • Custom • Duplicate submits • End States are one answer • Redirects are another <end-state id=“end” view=“redirect:springair.html?flowId=anotherFlow”/> • TransactionSynchronizer • Token-based implementation relies on a secure token to be present on the client and in flow scope • Interface is pluggable • Support for compensating transactions is of high interest to us: ended flow “rollback”
Issues and Solutions • Responding to the lifecycle of an executing flow • Listeners may be attached to executing flows • Callbacks are made on: • Request submitted – good for pre-flow event processing • Session starting – good for precondition checks • Session started -- good for post condition checks • Paused – good for custom view pre-render logic • Resumed – good for pre-flow event processing • State Entering – good for precondition checks • State Entered – good for post condition checks • Ended – good for custom cleanup logic • Request processed – good for post processing logic
Issues and Solutions • Annotating a Flow with metadata • Any flow definition artifact can be annotated: • Flow • State • Transition • An action’s use in a action state • Example: <action-state=“book”> <property name=“role” value=“passenger” type=“grantedAuthority”/> <action bean=“bookingAction”> <property name=“caption” value=“Books the reservation”/> </action> </action-state>
Issues and Solutions • Integrating into other environments • Create a specialized FlowController for that environment • For example: • The FlowAction for Struts • The FlowNavigationHandler for JSF • The PortletFlowController for Portlets • Spring Web Flow is not coupled with any other web framework • Not even Spring MVC or the Servlet API • Proven in a Portlet environment
Design Tips • What makes a good Web Flow? • Accomplishes some business goal, e.g. • Book a trip • Pay your taxes • Apply for a Loan • Encapsulates that business goal as a reusable module • A “black box” • Often has multiple paths to support different scenarios • Paths may vary based on contextual information • Often spawns other Flows as sub flows • Has a clear, observable lifecycle: Flow executions start, events happens, they end
Design Tips • What doesn’t make a good Flow? • Index pages • Welcome Pages • Menus • Simple Form Submissions (Mailers, etc.) • Sites with a lot of free navigation • Web flows are best suited for enforcing controlled navigation to support business process workflows • As a compliment to traditional controllers • Don’t abuse them
Spring Web Flow Road Map • JSF integration • JMX-enabled flow management • Ajax support • Asynchronous View State Actions • More configuration defaults • Research in the area of compensating transactions • Research in the area of asynchronous, parallel sub flows
Resources and Upcoming Events • www.springframework.org • New CMS portal means we now bring you a lot more content • Web Flow Wiki provides a “Quick Start” • Practical guide • Articles • Web Flow Ships with 7 sample applications • Phone Book (Core sample) • Sell Item (Wizard with Continuations) • Birth Date (Struts integration) • Item List (Transaction Synchronization) • Number Guess (Example of conversation history) • Flow Launcher (How to launch flows) • File Upload (A flow to upload files)
Resources and Upcoming Events • Public Spring Training • 4-day “bootcamps” across North America, Europe • www.springframework.com/training • The Spring Experience • International conference for agile Java developers • http://www.thespringexperience.com • December 7 – 10th, 2005, Sheraton Resort, Bal Harbour Beach Florida • 40+ technical sessions across four tracks: Web, Enterprise, Process, Beyond J2EE • Featuring • Rod Johnson (Spring Founder, i21 CEO) • Juergen Hoeller (Spring Co-Founder, i21 CTO) • Adrian Colyer (AspectJ Founder, i21 Chief Scientist) • Rob Harrop (Author, Pro Spring) • … and many more • Super early bird registration period open now
Conclusion • Spring is a complete, modular, pragmatic full-stack application framework • It adds serious value in: • The middle tier • The web tier • Spring 1.3 will be a major upgrade to the Spring web stack • Spring will continue to innovate • Spring will continue to simplify