Add new attachment

Only authorized users are allowed to upload new attachments.

This page (revision-1) was last changed on 11-Aug-2007 16:41 by UnknownAuthor

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Difference between version and

At line 1 added 76 lines
[Spring Web Flow|SpringWebFlow] is a form of "universal" application definition, whereby the application's structure becomes freed not only from a dependence on a particular web technology, but also on a particular delivery environment and even, in theory, programming language.
As of an early release (0.5) RSF featured a "lightweight" flow system modelled on a small subset of SWF, largely for demonstration purposes - this demonstrated the standard SWF "Number Guessing" sample running as an RSF application both in Servlets and Portlets. This demonstrated a somewhat "flatter" semantic on flows by allowing "back-transitions" in the flow without the expense of [continuations].
In the intervening years, SWF and RSF both moved on considerably from their respective positions, and SWF is an even more attractive target for RSF integration than it was then. As of RSF version 0.7.2, RSF features a full-scale integration with SWF, in which an SWF application may be transparently "embedded" in the RSF environment, with full interoperability with RSF templates, EL and navigation structures, as well as creating an indistinguishable environment on the client-side, to any Javascript or DHTML definitions.
Since SWF is based strongly on the Spring framework on which RSF is also based, there is a general harmonisation of programming idioms and aims. This page provides a central reference in converting SWF applications and structures to RSF. The best starting point for a general tutorial is to follow the port of the standard Spring Web Flow [Phonebook sample|PhonebookSWFSample], and for more advanced issues the [SellItem Samples|SellItemSWFSample].
%%(text-align:center)
[ImageHolder/swfphonebook-rsfswfsearch.png]
%%
!!! SWF in RSF
The SWF environment is presented within RSF as
* A set of standard "[binding|Bindings] beans", SWFBindingBean, SWFEventBean and SWFLaunchBean, which allow SWF operations to be triggered by means of RSF [EL] expressions] on [Action] cycles
* A hierarchy of standard [ViewParameters] objects, rooted at the base class [SWFViewParams], which allow SWF operations via render cycles.
* A set of framework-specific beans, generally hidden from the user, which coordinate i) the visibility of SWF flow-managed beans within RSF's request scope, and ii) the transfer and harmonisation of error messages and error states within the flow. In particular:
** All SWF beans visible at any of its flow scopes (in general, everything considered part of the "model" considered in SpringMVC terms) is both addressible by RSF [EL] and injectable from its request scope
** All binding and validation errors generated by the SWF system are transparently converted into the equivalent RSF [TargettedMessageList] list, suitable for distribution using the {{message-for:}} template syntax
Since the choice of passing bindings (form submissions) through the SWF system or handling it within RSF is simply a choice of binding target ({{SWFBindingBean}} or anything else), SWF-RSF applications can choose even on a bean-by-bean basis which binding system to use. This enables us to house both "standalone" SWF flows, like those in the basic [SellItem|SellItemSWFSample] sample, and "binding-free" flows, such as those in the JSF version of the same app, within the same integration, and even, if necessary, within the same application. This is discussed in more detail on the [SellItem|SellItemSWFSample] sample page.
!!Some examples
Here are some examples of invoking typical SWF operations from the RSF-SWF environment.
!Starting a flow
To launch a new flow (using a simple link), you can issue a [component|PrimitiveComponents] like this:
{{{
UIInternalLink.make(tofill, "sellitem-flow-link", new SWFLaunchViewParams(
"sellitem-flow"));
}}}
The argument to the {{SWFLaunchViewParams}} is the ID of the flow you want launched.
!Implementing a flow view state
Within RSF-SWF, the label of an SWF view name simply corresponds to the [viewID] of an RSF view. So for a flow view state declared so:
{{{
<view-state id="enterCategory" view="categoryForm">
}}}
one would implement the target view within the RSF application as
{{{
public class CategoryFormProducer implements ViewComponentProducer {
public final static String VIEW_ID = "categoryForm";
public String getViewID() {
return VIEW_ID;
}
}}}
!Submitting form data through SWF
To direct the submission of an RSF input component to a form object defined at the current flow action state, bind it to an [EL] path at the {{SWFBindingBean}}. Here is a little form from the [phonebook|PhonebookSWFSample]:
{{{
public void fillComponents(UIContainer tofill, ViewParameters viewparams,
ComponentChecker checker) {
UIForm form = UIForm.make(tofill, "search-form");
UIInput.make(form, "first-name", "SWFBindingBean.firstName");
UIInput.make(form, "last-name", "SWFBindingBean.lastName");
UICommand.make(form, "submit", "SWFEventBean.search");
}
}}}
This also demonstrates firing an SWF event named {{search}} - the corresponding flow state definition is
{{{
<view-state id="enterCriteria" view="searchCriteria">
<render-actions>
<action bean="formAction" method="setupForm"/>
</render-actions>
<transition on="search" to="displayResults">
<action bean="formAction" method="bindAndValidate"/>
</transition>
</view-state>
}}}
!!Render and Action cycles - GET and POST
One crucial web detail that is abstracted away by the Spring Web Flow system is the distinction between idempotent and non-idempotent requests. Whilst this has originated as an HTTP concept, the higher abstraction has become crucial in environments such as Portlets where render requests must be certainly re-issuable without disturbing application state. Spring Web Flow is careful to maintain the letter of the law, by __always__ redirecting after a flow transition to a fully refreshable URL, and so every SWF app, like every RSF app, will work correctly in an environment where idempotency is crucial. However, RSF achieves this safety whilst maintaining the distinct abstraction of render and action cycles visible to the framework user, so we have a slight mismatch of idioms between the two frameworks. As well as having the two varieties of {{SWFViewParams}} for launching new flows, and firing events in existing ones, we must have the corresponding binding targets for [Action] cycles:
|| ||Render cycle (UILink, UIForm with RENDER_REQUEST)||Action cycle (UICommand, UIForm with ACTION_REQUEST)
||Launching a flow|new SWFLaunchViewParams(flowId, <params>)| new UICommand(..., "SWFLaunchBean.flowId")
||Firing an event|new SWFEventViewParams(eventId, <params>)| new UICommand(..., "SWFEventBean.eventId")
To fire an SWF operation, then, using an action cycle, one can issue a [method binding|Bindings] attached to a UICommand component, that will, after the form submission has been processed ("binding", in Spring Web terminology), cause navigation along the flow in just the same way we showed above using simple links
Version Date Modified Size Author Changes ... Change note
11-Aug-2007 16:41 7.133 kB UnknownAuthor
« This page (revision-) was last changed on 11-Aug-2007 16:41 by UnknownAuthor