JSPWiki logo
Main page
About

Getting Started

Documentation
Developers
Javadocs
Designers
Sample RSF Apps
Presentations
Acronyms

Downloads
Current Release
Trunk
Distributions
Old Versions

Community
Q&A
Forums
Mailing Lists
Issue Tracker
People

Design
Roadmap
Integrations
Concepts
Philosophy

Pages
Find
Recent Changes
Unused
Undefined
Index

Set your name in
UserPreferences

Edit this page


Referenced by
SpringWebFlow




JSPWiki v2.2.33


HotelBookingSWFSample


On this page we will discuss the latest integration issues for Spring Web Flow (SWF) in RSF in the context of the SWF "Hotel Booking sample" sample. This page is meant for those who are familiar with SWF and RSF. if you are new to either one you should start on the RSF-SpringWebFlow page.

Sample Code (SVN): original code (with maven2 build) RSF SWF version

Try out Hotel Booking RSF SWF on our server

You can see the original sample in action on Ervacon's website.

Markup issues

The original sample was written using Facelets, a technology for JSF which allows a form of XHTML templating. This was further enhanced by the addition of tags from Spring Faces, the JSF integration for Spring Web Flow which is new for SWF 2.0. A sample of the Facelets markup is shown here:
<div class="label">
  <h:outputLabel for="beds">Room Preference:</h:outputLabel>
</div>
<div class="input">
  <h:selectOneMenu id="beds" value="#{booking.beds}">
    <f:selectItem itemLabel="One king-size bed" itemValue="1"/>
    <f:selectItem itemLabel="Two double beds" itemValue="2"/>
    <f:selectItem itemLabel="Three beds" itemValue="3"/>
  </h:selectOneMenu>
</div>

Whilst this is much improved over the JSP equivalent, in that it is a reasonably valid XHTML document, this markup is still unfriendly to designers, and also will give no useful behaviour when previewed in a browser. The tags in namespaces <f: and <h: will generally either not render at all, or else be skipped until valid XHTML tags are found within their body.

The equivalent section from the RSF template is

  <label class="label" for="booking_beds">Room Preference:</label>
  <select rsf:id="booking_beds" class="input">
    <option value="1">One king-size bed</option>
    <option value="2">Two double beds</option>
    <option value="3">Three beds</option>
  </select>

Not only does this use only recognised XHTML tags <label, <select, <option, which leads to this entire page previewing in the filesystem (check out the project in SVN, and browse to src/main/webapp/content/templates/bookingForm.html), there are also fewer tags. In a Facelets/JSF application, designer control generally ceases at the point where a component tag (e.g. <h:selectOneMenu appears - the markup at this point is replaced by that chosen by the component designer, written into the taglib. In RSF, the tags written in the templates are precisely the ones rendered, down to the last tag and attribute. Therefore there is no need for the extra layer of <div containment which is necessary to apply the CSS style target id input to the control - we can simply write this directly onto the <select tag itself. Similarly for the remainder of the document.

Outer templates

Like the Facelets composition system, RSF allows markup templates to be drawn up that can be "included" from anywhere else in the application, using its Outer Page Templates scheme. Unlike Facelets compositions, this again occurs without the need for custom tags, and without compromising previeawability.

Application transparency

RSF is a "model free" framework. This does not mean it has no model layer, rather that it has no model definitions within the framework that require wrapping of client model definitions. Unlike JSF's Table, List and Tree model classes, RSF view trees are generated programmatically using normal Java code constructs such as for loops. The original sample contains a utility class SerializableListDataModel which is required to adapt the Booking and Hotel Lists used in the application to JSF's requirements. In RSF, we perform such iteration directly in code:
  for (Hotel hotel : hotels) {
    UIBranchContainer hotelrow = UIBranchContainer.make(tofill, "hotel-row:");
    HotelUtil.dumpHotel(hotelrow, hotel);
    UIInternalLink.make(hotelrow, "view-hotel", 
    new SWFEventViewParams("selectHotel", MapUtil.make("hotelId", hotel.getId())));
    }

Validation

The current validation code in the Spring Faces sample is labelled as provisional and will be replaced by a more scripted style in future versions of Spring Web Flow. As it stands it has dependencies on both JSF and on SWF and requires to be recast. In the RSF version of this app we fall back to a pure Spring Binding approach, using the standard Spring framework FormAction action handler and Spring Validators. Some (non-RSF-dependent) extensions are provided for this model, making it highly convenient and compact to specify validation rules in a technology-neutral fashion. ultimately paving the way for client-side validation. Here is the definition for the "Booking action" bean, replacing the custom BookingActions held in the original application:
  <bean id="bookingActions"
    class="org.springframework.webflow.samples.booking.flow.booking.BookingActions">
    <property name="formObjectName" value="booking" />
    <property name="validator">
      <bean class="org.springframework.webflow.samples.booking.flow.booking.BookingValidator" />
    </property>
    <property name="validatorSpecs">
      <list>
        <value>creditCard: required, positive, maxLength(16), minLength(16)</value>
        <value>creditCardName: required</value>
      </list>
    </property>
  </bean>

The Java code itself is split into two packages, a standard Spring Validator

public class BookingValidator implements Validator {

  public boolean supports(Class clazz) {
    return Booking.class.isAssignableFrom(clazz); 
  }

  public void validate(Object bookingo, Errors errors) {
    Booking booking = (Booking) bookingo;
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DAY_OF_MONTH, -1);
    
    if (booking.getCheckinDate().before(calendar.getTime())) {
      errors.rejectValue("checkinDate", "error-date-future");
    }
    else if (!booking.getCheckinDate().before(booking.getCheckoutDate())) {
      errors.rejectValue("checkoutDate", "error-checkout-earlier");
    }
  }

}
and then the remainder of the booking flow setup code, responsible for constructing the initial booking record, packaged as the createFormObject method of the FormAction (now extending the intermediate helper class ValidatorFormAction:
public class BookingActions extends ValidatorFormAction {
  protected Object createFormObject(RequestContext context) throws Exception {
    Hotel hotel = (Hotel) context.getFlowScope().get("hotel");
    User user = (User) context.getConversationScope().get("user");
    Booking booking = new Booking(hotel, user);
    EntityManager em = (EntityManager) context.getFlowScope().get("entityManager");
    em.persist(booking);
    return booking;
  }
}
Spring Web Flow 2.0 final is expected to have facilities to avoid this lookup code. RSF version 0.8 will independently feature lookup-free handling of all kinds of "intermediate" scopes, such as flow, session and conversation. We have at least so far managed to remove all non-SWF dependencies from this application beyond the rendering layer.

Automatic AJAX transparency

Keeping track of flow keys and URL state can be a hazard when trying to conduct AJAX development together with SWF. RSF's ViewParameters scheme allows us to abstract all these details away - the framework automatically applies a flow-state-specific "fixup" to any URLs issued to clients to ensure they are properly nested within any current flow state. This enables the full set of RSF AJAX-enabled components, such as the internationalised date widget, to be used transparently within an SWF application with no modification. The AJAX round-trips performed by the widget are automatically "fixed up" to access the current flow state. As more components are developed as part of the Fluid UI Project this will fruitfully feed forwards into a stream of fully accessible, flexible and generic which are usable both within SWF and without.




Go to top   Edit this page   More info...   Attach file...
This page last changed on 14-Sep-2007 13:26:28 UTC by AntranigBasman.