Saturday, February 28, 2009

Spring Webflow: An elegant DSL for your MVC

Spring Web Flow is an interesting MVC framework. Under the hood, it is an implementation of a Finite State Machine (FSM). However, the beauty of Spring Web Flow is in the simplified DSL templating that Web Flow provides.

First, lets look at a simple example:
<flow start-state="start">

<view-state id="start" view="chooseColor.jsp">
<transition on="red" to="showRed" />
</view-state>

<end-state id="showRed" view="red.jsp"/>

</flow>

This web flow above has two states and one transition. States in web flow typically correspond to views. In this case, my views are JSP's. Transitions will be triggered based on events. Within a JSP, events correspond to buttons or links. The event or button to trigger the red event is defined here:

<html>
...

<form:form action="${flowExecutionUrl}">
<input type="submit" name="_eventId_red" value="Red" />
</form:form>

...
</html>


The flowExecutionUrl contains the context-relative URL to the current flow execution's view state. Alright, so what advantages does web flow provide? Here are a few:

  • Do your business users create use cases or flow charts? If they do, those documents should map uniformly to web flows. In fact, the business users that build the flow charts should be able to interpret your web flow definitions also. Self documenting code that you can also share with the business is valuable.

  • Spring Web Flow provides an additional scope called flowScope. Most applications suffer from session bloat because many developers put data into session out of convenience and do not always think about its consequence. Web Flow alleviates this problem with their flow scope. For example, flow scope is created when your flow starts. And when your flow ends, all data held within flow scope is cleaned up automatically. Now you are running lean! In the example below we put a list of colors in flowScope:
    <flow start-state="start">

    <view-state id="start" view="chooseColor.jsp">
    <on-render>
    <evaluate
    expression="colorService.findAllColors()" 
    result="flowScope.colors" />
    </on-render>

    <transition on="red" to="showRed" />
    </view-state>

    <end-state id="showRed" view="red.jsp"/>
    </flow>



  • Spring Web Flow also has a built-in expression language. The expression language is a feature that allows you to call your Spring beans conveniently from within your flows. In the example above, we fetched our colors from the ColorService.

  • There is less code to maintain compared to the other MVC frameworks. You do not need controller objects anymore. However, you still need to create model objects for binding form data to objects. The form binding in web flow is automatic for simple types.

  • Your flows and transitions can be secured with Spring Security. The example below shows how you may secure your web flow or a transition:
    <flow start-state="start">
    <!-- secure the entire flow -->
    <secured attributes="ROLE_USER" />

    <view-state id="start" view="chooseColor.jsp">
    <transition on="red" to="showRed">
    <!-- secure this transition -->
    <secured attributes="ROLE_ADMIN"/>
    </transition>
    </view-state>

    <end-state id="showRed" view="red.jsp"/>

    </flow>



  • You can achieve reuse with subflows and global transitions.
    <flow start-state="start">

    <view-state id="start" view="chooseColor.jsp">
    <transition on="red" to="showRedSubflow" />
    <transition on="green" to="showGreenSubflow" />
    </view-state>

    <!-- subflow states -->
    <subflow-state id="showRedSubflow"
    subflow="redSubflow.jsp" />
    <subflow-state id="showGreenSubflow"
    subflow="greenSubflow.jsp" />

    <end-state id="thankYou" view="thanks.jsp" />

    <!-- If every page had a cancel button we may declare that transition once. -->
    <global-transitions>
    <transition on="cancel" to="cancel.jsp" />
    </global-transitions>

    </flow>



  • Web flows are browser button friendly. To achieve this, every view state rendered gets stored as a snapshot. When you press the back button, the previous snapshot is retrieved from the snapshot repository. For performance, you may limit the number of snapshots that exist within the snapshot repository.

  • Web flows eliminate the double-submit problem. To accomplish this, Spring will apply the POST-REDIRECT-GET pattern to all POST requests. You may also disable this feature if it's not needed or if you want better performance.

  • As always, Spring has strong JUnit test support to help test your flows.



In conclusion, Spring Web Flow is a very unique MVC framework. It is an ideal solution for simplifying complex work flows. I particularly like the simplicity of the domain specific templating language (DSL), the flowScope, and the expression language capabilities.

No comments :

Post a Comment