Spring Web Flow - 1.0

Extension ID

com.castsoftware.springwebflow

What’s new?

See Spring Web Flow - 1.0 - Release Notes for more information.

Description

This extension provides support for Spring Web Flow.

In what situation should you install this extension?

The main purpose of this extension is to create Spring Web Flow objects, to enable linking from a Web application front end to Java methods to which it refers to. Therefore if your Web application contains source code which uses Spring Web Flow and if you need to view links from a Client Front-end to the Spring JEE Back-end then you should install this extension.

If the pom.xml of your application contains the following dependency:

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>spring-webflow</artifactId>
    <version>2.4.2.RELEASE</version>
</dependency>

and if your application contains XML files with the following XML Schema definition:

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
       http://www.springframework.org/schema/webflow
       http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

then you should install this extension.

Features

This extension handles Spring Web Flow used in JEE applications, for example:

Spring Web Flow XML File

<flow xmlns="http://www.springframework.org/schema/webflow"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/webflow
  http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

 <var name="searchCriteria" class="org.springframework.webflow.samples.booking.SearchCriteria"/>
 
 <view-state id="enterSearchCriteria">
   <on-render>
     <evaluate expression="bookingService.findBookings(currentUser?.name)"
      result="viewScope.bookings" result-type="dataModel" />
   </on-render>
   <transition on="search" to="reviewHotels"/>
   <transition on="cancelBooking">
     <evaluate expression="bookingService.cancelBooking(bookings.selectedRow)" />
   </transition>
 </view-state>
</flow> 

Spring Web Flow is composed of a set of ‘states’ (displaying a view or executing any action etc.). Transition of the flow from one state to another is triggered by an event.

The important Spring Web Flow States are:

  • view-state
  • action-state
  • decision-state
  • subflow-state
  • end-state

For each state that contains calls to java methods either using <evaluate> node or <set> node, the following will be done:

  • a Spring Web Flow state object will be created
    • if it is a view-state object, the corresponding front end object will be linked to this Spring Web Flow state object
    • if it is an action-state/decision-state object, the Spring Web Flow object that invokes the action/decision state object is linked
  • links to java methods which the Spring Web Flow state invokes, are created

Spring Web Flow view-state

Entering a view-state typically results in a view being displayed to the user. On that view, user events occur that are handled by the state.

The following Spring Web Flow XML code:

<view-state id="enterSearchCriteria">
  <on-render>
   <evaluate expression="bookingService.findBookings(currentUser?.name)"
    result="viewScope.bookings" result-type="dataModel" />
  </on-render>
  <transition on="search" to="reviewHotels"/>
  <transition on="cancelBooking">
   <evaluate expression="bookingService.cancelBooking(bookings.selectedRow)" />
  </transition>
 </view-state>

will generate:

  • A view-state when entered pauses the flow and returns the control to the client/user and the flow is resumed on the user/client event which resumes the flow and triggers the transition to the state depending on the user/client input or decision.
  • Since the view-state waits for the user input that takes place in the view, a callLink is created from the corresponding view page to the respective Spring Web Flow object.
  • The view-state invokes Java methods in the <evaluate> or <set> tags. Call links are created from the Spring Web Flow state object to java methods that the state invokes.
  • The java method is invoked using a java object(Spring Bean) or a flow variable. Using the class type of the java object, we determine the specific java methods to be linked with the Spring Web Flow state object.

Spring Web Flow action-state

The action state executes a particular action. Spring Web Flow action-state always encloses a <evaluate> or <set> action elements that invoke java methods.

The following Spring Web Flow XML code:

 <view-state id="start" view="memberDetails" model="flowScope.userBean">
   <transition on="submit" to="validate" />
 </view-state>
 <action-state id="validate">
   <evaluate expression="demohandler.validateDetails(userBean,messageContext)"></evaluate>
   <transition on="success" to="confirmDetails" />
   <transition on="failure" to="start" />
 </action-state>
 <view-state id="confirmDetails" view="confirmDetails" model="flowScope.userBean">
   <transition on="edit" to="start" />
   <transition on="submit" to="welcome" />
 </view-state>

will generate:

As seen in the code snippet above, the view-state ‘start’, on occurrence of a particular user event, invokes the action-state ‘validate’ and hence the callLink from the Spring Web Flow State object ‘start’ to the Spring Web Flow state object ‘validate’. The action-state invokes the ‘validateDetails’ method and hence the callLink from the Spring Web Flow object ‘validate’ to the java method ‘validateDetails’.

Spring Web Flow decision-state

The decision-state is an alternative to the action-state to make a routing decision using a convenient if/else syntax. A decision-state is used to determine the next state in the dynamic way or at runtime. Spring Web Flow decision-state always encloses a action element that invoke java methods.

The following Spring Web Flow XML code:

<view-state id="passengerdetail" model="passenger">
  <on-render>
    <evaluate expression="bookingFactory.createPassenger()" result="viewScope.passenger" />   
    <evaluate expression="bookingFactory.getNumberOfPassenger(flowScope.booking)" result="viewScope.numberofpassenger" />
    <evaluate expression="bookingFactory.getSeatAlreadyBooked(flowScope.booking)" result="viewScope.seatalreadybooked" />
  </on-render>
  <transition to="passengerdetail" on="addpassenger">   
    <evaluate expression="bookingValidator.validatePassenger(viewScope.passenger, messageContext)" />   
    <evaluate expression="bookingFactory.addPassenger(flowScope.booking,viewScope.passenger)" />
  </transition>
  <transition to="frequenttraveller" on="next">
    <evaluate expression="bookingValidator.validatePassengerNumber(flowScope.booking, messageContext)" />
  </transition>
  <transition to="timetable" on="previous"></transition>
 </view-state>
 
 <decision-state id="frequenttraveller">
   <if test="bookingFactory.isFrequentTraveller(flowScope.booking)" then="congratfrequenttraveller" 
  else="reviewbooking" />
 </decision-state>

will generate:

As seen in the code snippet above, the view-state ‘passengerdetail’ transits to decision-state ‘frequenttraveller’ on occurrence of a user event. Hence the callLink from Spring Web Flow State ‘passengerdetail’ to Spring Web Flow decision-state object ‘frequenttraveller’. On entering the decision-state ‘frequenttraveller’, the java method ‘isFrequentTraveller’ is invoked in the <if> element. Hence the callLink from Spring Web Flow object ‘frequenttraveller’ to the java method object ‘isFrequentTraveller’.

Spring Web Flow subflow-state

A flow may call another flow as a subflow. The flow will wait until the subflow returns, then respond to the subflow outcome. The modelisation for subflow-state is same as that of action-state. The subflow-state is invoked by main flow state.

The following Spring Web Flow XML code:

<view-state id="loginForm" view="login" model="user">
    <transition on="submit" to="actionCheckLogin"/>     
    <transition on="createUser" to="createUserFlow" validate="false"/>
</view-state>

<subflow-state id="createUserFlow" subflow="createuser-flow">
    <input name="user"/>
    <evaluate expression="userService.userExist(user,flowRequestContext)"/>
    <transition on="userCreated" to="loginForm"/>
    <transition on="cancelled" to="home"/>
</subflow-state>

will generate:

As seen in the code snippet above, the view-state ’loginForm’ invokes the subflow-state ‘createUserFlow’ on occurrence of a user event. Hence the callLink from Spring Web Flow State ’loginForm’ to Spring Web Flow subflow-state object ‘createUserFlow’. The state ’loginForm’ then waits for subflow to return and then resumes the main flow. The subflow-state evaluates ‘userExist’ java method. A property is set on the Spring Web Flow state object to indicate that it is a subflow-state.

Spring Web Flow on-start

In Spring Web Flow, there is always a start state, which helps in creating the initial state of the flow. If the start state is not specified, the first view state becomes the start state.

The element is defined in the beginning of the flow before defining the Spring Web Flow states in flow file. All the expressions within the tag are resolved first before the flow reaches the start state. Hence the is made part of the first occurring Spring Web Flow state object (i.e start-state) according to the modelisation.

The element may enclose / nodes that invoke java methods.

The following Spring Web Flow XML code:

<!-- Executed when webFlow is triggered -->
<on-start>
    <!-- demohandler is java class available through annotated Demohandler.java 
    class.here we are calling it’s initFlow() method. -->
    <evaluate expression="demohandler.initFlow()" result="flowScope.userBean" />
</on-start>

<!-- if not specified the first view state is the starting state -->
<view-state id="start" view="memberDetails" model="flowScope.userBean">
    <transition on="submit" to="validate" />
</view-state>

will generate:

The <on-start> which is a part of the first state element - “start” invokes the java method “initFlow”, and hence the call Link is created.

Spring Web Flow global-transitions

The global-transitions’ action elements apply across all views. Global-transitions are often used to handle global menu links that are part of the layout. So the <evaluate> of the global transitions are made part of all Spring Web Flow states.

The following Spring Web Flow XML code:

 <on-start>
    <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" result="flowScope.booking" />
 </on-start>
 
 <view-state id="enterBookingDetails" model="booking">
     <transition on="proceed" to="reviewBooking" />     
     <transition on="cancel" to="bookingCancelled" bind="false" />
 </view-state>
 
 <view-state id="reviewBooking">
     <transition on="confirm" to="bookingConfirmed">
         <evaluate expression="bookingService.persistBooking(booking)" />     
     </transition>
     <transition on="revise" to="enterBookingDetails" />
     <transition on="cancel" to="bookingCancelled" />
 </view-state>
 
 <end-state id="bookingConfirmed" />
 <end-state id="bookingCancelled" />
 
 <global-transitions>
     <transition on="cancel" to="bookingCancelled">
         <evaluate expression="bookingService.cancelBooking(booking)"/>
     </transition>
 </global-transitions>

will generate:

As per the code, both the state elements “enterBookingDetails” and “reviewBooking” call the “cancelBooking” java method as it is evaluated in the <global-transitions>.

The <global-transitions> are found the at end of the flow.

Spring Web Flow model-view binding

The model attribute in the view-state element declares a model object the view binds to. It enables form data binding and validation behaviors to be driven from metadata on the model object. Specifying a model triggers the following behavior when a view event occurs:

  • View-to-model binding. On view post back, user input values are bound to model object properties for you

  • Model validation. After binding, if the model object requires validation that validation logic will be invoked

As per the modelization, we choose to link the view object to the corresponding java setter methods, which are nothing but the model object properties.  The following Spring Web Flow XML code:

<flow xmlns="http://www.springframework.org/schema/webflow"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
 http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd" start-state="searchBooksForm"> 
 
  <var name="bookCriteria" class="khn.library.proj.domain.search.BookCriteria"/>
  
  <view-state id="searchBooksForm" model="bookCriteria" >   
      <transition on="search" to="processSearch" ></transition>
  </view-state>
  
  <action-state id="processSearch" >
      <set name="flowScope.booksFound" value = "bookService.search(bookCriteria)" />
      <transition on="success" to="bookList" />    
  </action-state>
  
  <view-state id="bookList">
      <transition on="next" to="endState" />
  </view-state>
  
  <end-state id="endState"/>  
</flow>

will generate:

The view object searchBooksForm.jsp is linked to the java setter methods setAuthor and setKeyword via call links according to the modelization. author and keyword are the model properties.

Specifying bindings explicitly

The <binder> element is used to configure the exact set of model bindings usable by the view. This is particularly useful in a Spring MVC environment for restricting the set of “allowed fields” per view. If the binder element is not specified, all public properties of the model are eligible for binding by the view. With the binder element specified, only the explicitly configured bindings are allowed.

The following Spring Web Flow XML code:

 <var name="pojoComunidades" class="com.aironman.core.pojos.ComunidadVecinos" />
 <var name="pojoFincas" class="com.aironman.core.pojos.ViviendasConDeudas" />
 <var name="pojoMorosos" class="com.aironman.core.pojos.Moroso" />
 <var name="pojoJuntas" class="com.aironman.core.pojos.JuntasOrdinarias" />
 <var name="pojoViviendas" class="com.aironman.core.pojos.ViviendasConDeudas" />
 
 <view-state id="juntas" model="pojoJuntas">
    <binder>
       <binding property="idJunta" required="false"/>
       <binding property="fechaCelebracion" required="true"/>
       <binding property="textoLibre" required="true"/>
     </binder>
     <transition on="guardarJunta" to="addJuntaAction" validate="true" />
     <transition on="avanzarAComunidades" to="comunidades" validate="false"/>
     <transition on="inicio" to="index1" validate="false" />
 </view-state>

will generate:

As seen in the above code, since <binder> element is used, the view object is linked to only specified java setter methods whose properties are defined in the <binder> element.

Function Point, Quality and Sizing support

This extension provides the following support:

Function Points
(transactions)
Quality and Sizing
(tick) (error)

CAST AIP compatibility

This extension is compatible with:

CAST AIP release Supported
8.3.x (tick)

Packaging, delivering and analyzing your source code

Once the extension is installed, no further configuration changes are required before you can package your source code and run an analysis. The process of packaging, delivering and analyzing your source code does not change in any way:

  • Package and deliver your application (that includes source code which uses Spring Web Flow) in the exact same way as you always have.
  • Analyze your delivered application source code in the CAST Management Studio in the exact same way as you always have - the source code which uses Spring Web Flow will be detected and handled correctly.

What results can you expect?

Once the analysis/snapshot generation has completed, Spring Web Flow objects will be available that act as a bridge between front end objects and back end Java method objects as shown in the screenshot below:

Objects

Server Side

The following objects are displayed in CAST Enlighten on the Java side:

Icon Description

Spring Web Flow State

Rules

None.