%%(font-size: 2em; color:red;)
RSF-SWF Planning page - for current info, go to the [RSF SpringWebFlow page|SpringWebFlow]
%%
''This page is not suitable for RSF users and is meant for those who want to get a sense of our development process only'' - RSF team

This page documents the effort to integrate RSF as a view technology for [Spring Web Flow|SpringWebFlow]. As of RSF 0.5, RSF had 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.

SWF has moved on considerably in the 2 years since that point, and is an even more attractive target for RSF integration than it was then. SWF 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. Since SWF is based strongly on the Spring framework on which RSF is also based, there is expected to be a general harmonisation of programming idioms and aims (although with a few mismatches owing to RSF's stronger promotion of the "request scope" as a core abstraction). 

Spring applications are currently missing a natural "Spring-like" front end, with the existing integrations for SWF (being JSF, Struts, and the SpringMVC family) being based on more old fashioned "action" oriented request processing and poor (to none) separation of markup and view logic. RSF-SWF is planned to provide a harmonious environment where users can enjoy the separation of their concerns equally at every level of application design, right out to the front end where designers may work on pure HTML in peace.

!!!Integration Goals
It is a key goal that an RSF-SWF app be not in any way "special" as an RSF app, but that users may be able to step out of the SWF world with no formality when required, to make use of general environmental RSF capabilities. This is since a key part of the integration goal is to enable the natural use of the predefined RSF "widgets" (many of which arising from work on the [Fluid project|http://fluidproject.org/]), which should be usable in SWF and non-SWF applications alike.

The plan is to expose zero evidence by the time we reach the client side that we are dealing with an SWF app - in that the same binding and ID environment presented by all RSF applications will be in force. Further, those components which require the use of RSF [transit beans|TransitBeans] should continue to function, which implies that a standard RSF POST submission cycle and request scope should apparently be in force to the outside world.

!!!Integration Plan
!! Proxy bean(s) for EL target
A key part of meeting these goals in the integration plan is to provide one (or two) central "proxy beans" within the RSF environment which provide the bridge to the internal "SWF world" operated by the flow definitions. These beans will be responsive to both standard RSF submission bindings, and also will act as a proxy for RSF action (method) bindings to move along the flow state.
!! Special ViewParameters for SWF views
An SWF "GET" link does not work as is standard in HTML/HTTP - rather than being a link to a particular ''view'' or ''resource'', it corresponds to a transition within the flow map. That is, it represents a instruction to ''decode'' a particular view by operating the flow transitions, rather than the view itself. It is impossible to prevent this change in interpretation from propagating to the [view producer|ComponentProducer] layer in RSF, since it is a fundamental alteration in semantics. In RSF, a "standard" [ViewParameters] object directly represents a resolution onto a particular view (in particular it encodes a View ID). 
Therefore all __links__ in an RSF-SWF app which are interpreted as SWF transitions must be encoded as a special class of ViewParameters, even if (as is expected/hoped), the views themselves are using more concrete/simple VPs as their own inputs (to locate themselves).

!Example - Phonebook app
The remainder of this treatment will illustrate the motivation and mechanism of the integration by quoting various aspects of the JSP implementation of the standard SWF sample, the "phonebook app" and showing how these will be rendered in the RSF integration.

Firstly to round out our discussion of GET links and ViewParameters, here is a "template" section from the phonebook application rendering a link (or rather list of links) [[from {{details.jsp}}]:
{{{
<b>Colleagues:</b>
  <br>
  <c:forEach var="colleague" items="${person.colleagues}">
   <a href="phonebook.htm?_flowExecutionKey=${flowExecutionKey}&_eventId=select&id=${colleague.id}">
   ${colleague.firstName} ${colleague.lastName}<br>
  </a>
</c:forEach>
}}}
The corresponding part of the flow definition is [[from {{detail-flow.xml}}]
{{{
<view-state id="displayDetails" view="details">
  <render-actions>
    <bean-action bean="phonebook" method="getPerson">
      <method-arguments>
        <argument expression="flowScope.id" />
       </method-arguments>
       <method-result name="person" />
     </bean-action>
   </render-actions>
   <transition on="back" to="finish" />
   <transition on="select" to="browseColleagueDetails" />
</view-state>
}}}

As we see, the key information supplied to the link, appearing as the {{_eventId=select}} parameter, is actually a flow ''transition'', matching the {{   <transition on="select" to="browseColleagueDetails" />}} section in the definition for this "view state" (labelled by being marked as {{view="details"}} in the flow definition.


This JSP sample is pretty nasty, not only does it irreversibly pollute the view template, it also exposes to the developer ALL the peculiar requirements of the SWF integration. This example illuminates what the space of SWF view parameters is intended to be, but also what we would like to assist the developer with as much as possible. As a draft ViewParameters then, we arrive at something like this:
{{{
public class SWFViewParameters extends SimpleViewParameters {
   public String eventId;
   public Map<String, String[]> parameters;
}
}}}
We cannot avoid the fact that in SWF, view parameters are essentially "unstructured" - since we cannot guess the final view state, we also cannot guess what organisation would be appropriate for its state. However we at least *can* get link-safety on the {{eventId}} field, and also (since RSF was originally planned with an inspection of SWF concepts) can economise on the flow variables by using the {{flowtoken}} field that has always been present in the base class {{ViewParameters}}. %%(color:red;font-weight:bold)Probably need to do a bit of juggling here, since the interpretation may not match completely%%. We would make a direct correspondence between the SWF {{view}} value and an RSF {{viewId}}.

We would *hopefully* be able to retain some kind of "native" VP support in the target view. This would require a *fixed* parseSpec on those VPs which would be in visible correspondence with the SWF parameter map, though. %%(color:red; font-weight:bold)__IDEA__ - perhaps we could instead of {{parameters}}, actually include ANOTHER vp object, one that is known to be good for the end view or views, whichever those are. %%

So - in our RSF app, the UILink for this transition would look something like
{{{
for (Colleague colleague: colleagues) {
   UILink.make(tofill, "select-link:", 
      new SWFViewParameters("select", "id", colleague.id);
}
}}}
assuming a convenience constructor that accepted a single key/value pair - we would probably make at least two of these. The problem with the "nested ViewParams" concept was that the 2nd ViewParams would necessarily have to omit the viewID of the view, which is not really up to the client to determine. This would look a bit odd.

We probably want to add a "fixup" stage in RSF that would copy in the current {{flowtoken}} into any VP object found in the tree. This had previously been something up to the application developer, but on discovering an SWFVP it should be fairly clear that they are intending for flow semantics to become automated.

!!Proxy bean, handling forms

Back to the proxy bean, again illustrated from PhoneBook.

Here is an SWF form in JSP, [[from {{searchCriteria.jsp}}]
{{{
  <form:form commandName="searchCriteria" method="post">
    <table>
      <tr>
        <td>Search Criteria</td>
      </tr>
      <tr>
        <td colspan="2"><hr></td>
      </tr>
      <tr>
        <td colspan="2">
          <form:errors cssClass="error"/>
        </td>
        </tr>
        <tr>
          <td>First Name</td>
          <td><form:input path="firstName" /></td>
        </tr>
        <tr>
          <td>Last Name</td>
          <td><form:input path="lastName" /></td>
        </tr>
      <tr>
        <td colspan="2" class="buttonBar">
          <input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
          <input type="submit" class="button" name="_eventId_search" value="Search">
        </td>
      </tr>		
    </table>
  </form:form>
}}}

Well, what do we see here? (apart from the terrible table-driven markup :P) More mixed stuff we want to shield the developer from. The "_flowExecutionKey" and special naming on the {{submit}} button as well as the strange new {{commandName}} argument are our key targets... to be fair, these are details which are also missing in the JSF integration for SWF, but there the penalty is that the developer needs to use the rest of JSF!

Anyway, we need to consider what will be the treatment of {{UIForm}}, {{UIInput}} etc. and {{UICommand}}, to match our treatment of {{UILink}} above.

For a start, all SWF "events" on action cycles will be invoked as if a synthetic "method" on the "flow proxy bean". So, for our {{submit}} button above, we will have 

{{{
  UICommand.make(tofill, "search-control", "SWFProxyBean.search");
}}}
%%(color:red; font-weight:bold)Probably looking for a better name than SWFProxyBean%%

This is pretty easy to implement in current RSF, since we already put in the key interface {{ActionTarget}} in order to do our 0.5 SWF ripoff.

Next, the UIInput controls - SWF operates a traditional SpringMVC/Struts-type "single bean submission model" whereby the bean to be submitted against for each action cycle is a single one - set up in a definition like this one [[from search-flow-beans.xml]:
{{{
  <!-- Search form action that setups the form and processes form submissions -->
    <bean id="formAction" class="org.springframework.webflow.action.FormAction">
      <property name="formObjectClass" value="org.springframework.webflow.samples.phonebook.SearchCriteria"/>
      <property name="validator">
        <bean class="org.springframework.webflow.samples.phonebook.SearchCriteriaValidator"/>
    </property>
  </bean>
}}}

Note that this "minicontext" file is actually imported INTO the definition and hence scope of the flow with this directive in the flow definition:

{{{
   <import resource="search-flow-beans.xml"/>
}}}
This is a "bit funny" in RSF terms, if only because we tend to favour "exterior" aggregation of context files rather than having internal references. Luckily it is nothing to do with us since we will always let SWF itself handle such things, but it is worth noting as a bit of an idiomatic shift.

ANYWAY, also an idiomatic shift is the fact that the target of the form submission is a "blank bean" identified by the following "constructor" {{      <property name="formObjectClass" value="org.springframework.webflow.samples.phonebook.SearchCriteria"/>}}, rather than being a first-class request-scope bean as it would be in RSF. We will set up the standard that we will address "this bean", whichever it is for the current form submission, as if it itself were the same SWFProxyBean we had before %%(color:red; font-weight:bold)Should it have a different name?%%

So, the UIInputs for this view would be something like :

{{{
   UIInput.make(tofill, "input-firstName", "#{SWFProxyBean.firstName}");
   UIInput.make(tofill, "input-lastName", "#{SWFProxyBean.lastName}");
}}}

This just leaves us with the form itself to map. %%(color:red; font-weight:bold)The {{commandName}} on the form SEEMS to be in correspondence with the view name? Why is this here?%% In the JSF app the form is identified simply by id, which we would not do in RSF to avoid polluting the client space. 

The corresponding view state definition for this view is [[from {{search-flow.xml}}]
{{{
  <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>
}}}
!!Mocking up the Action environment
So on the face of it, the only configuration required to identify the incoming binding is for the {{transition}}, which we have already seen in the UICommand above. We would just use the binding {{#{SWFProxyBean.search} }} as we did there. If {{commandName}} doesn't do anything vital, we just need some way of communicating to the forthcoming action cycle that it needs to do "special things" with the model - but actually the action cycle does VERY LITTLE special with the model since as soon as we pass the formality of meeting the action method proxy, we are 100% in the SWF world as regards submission data. The bindings incoming over the EL would have been "collected" using a DARReceiver, and then used to "fake up" a submission environment into a RequestContext of the sort the Spring Binder would be expecting (we would probably initially only mock up one specific kind of these, the standard "WebDataBinder" that expects paired key/value pairs with a very "skinny fossil" with an underscore in front of the key to represent an "expected request value".

!!Action return
SWF has a fairly rigid set of cases it expects to result from action returns, these are encoded in the {{ResponseInstruction}} returns which are given to the environment. In RSF, the return result from an action cycle is ALWAYS mapped into a ViewParameters, so we need some special kind of ARIInterpreter that kicks in - this is just like we already have for flow "lite". This table relates the SWF flow conditions to the best corresponding ones from the existing RSF "ARIResult" system.

See the MVC {{FlowController}} - there are 4 basic flow result cases.
|Condition|Comment|RSF interpretation|RSF flow condition
|handleApplicationView|forward to a view as part of an active conversation|A normal RSF ViewParameters - not SWFViewParams since we expect/hope we have fully located the desired flow state and hence viewId by this point.|AriResult.PROPAGATE
|handleFlowDefinitionRedirect|restart the flow by redirecting to flow launch URL|"restart" seems an odd way of expressing it, but I suppose SWF has no concept of a view state that *had* not already been in a flow|AriResult.FLOW_START
|handleFlowExecutionRedirect|redirect to active flow execution URL|This one is a bit peculiar, not sure why it requires a separate case to applicationView|AriResult.PROPAGATE, but with a different flowtoken?
|handleExternalRedirect|redirect to external URL|Fairly clear|AriResult.FLOW_END, and with a {{resultingView}} of type RawViewParameters.

!!Flow scopes and view producers
The remaining piece of the puzzle is how to gain access to flow scoped variables from inside ViewProducers. For simple cases, we will expect these to be addressible directly via EL. However, for complex cases where the view structure will depend on the flow variables, this is an area in which there *will* be some redundancy, since the natural RSF idiom, given these *already* sit in Spring is simply to inject the bean results into the producers directly. We will have to handle this by a scheme somewhat similar to the "bean inchuck" scheme for SpringMVC integration - the user will have to write ''fake beans'' into the context that represent the name and type of the bean which is ''expected to be there'' on the render cycle, but the actual instance used will appear "by magic" at the start of the alteration cycle, overlaying the bean definition and preventing it from being instantiated.

There are a couple of ways we have seen that variables can get into flow scope, here is one, using the {{<render-actions>}} directive [[from {{search-flow.xml}}]:

{{{
  <view-state id="displayResults" view="searchResults">
    <render-actions>
      <bean-action bean="phonebook" method="search">
        <method-arguments>
          <argument expression="flowScope.searchCriteria"/>			
        </method-arguments>
        <method-result name="results"/>
        </bean-action>
      </render-actions>
    <transition on="newSearch" to="enterCriteria"/>
    <transition on="select" to="browseDetails"/>
  </view-state>
}}}

Personally I find this verbose "bean-action" stuff probably the worst aspect of SWF, but what else can you do if you want an abstract application model expressed with no code... The key point is that the {{<method-result name="results"/>}} directive is intending to deposit a bean into flow scope that a Producer might expect to access, either by EL or direct injection. The "inchuck" method, assuming we wanted direct injection, would require us to make a "fake bean" definition in RSF request scope like this:

{{{
  <bean id="results" class="java.util.List"/>
}}}
Hopefully we would get away with the fact that this bean is technically uninstantiable since its class is uninstantiable - the whole point of this is to be able to make SpringIDE shut up, so that it sees the injection is proceeding from a compatible type, and also to tell the RSF injector (run by RSAC) what is the ''association'' between the name of the bean, and the producer property it is intended to be delivered by - so if we needed access to these "results" directly (which we certainly would, since we have a loop counter variable which depends on its size), we would have something like

{{{
  <bean class="org.springframework.webflow.samples.phonebook.rsf.SearchResultsProducer">
    <property name="searchResults" ref="results"/>
  </bean>
}}}

So then we would have injection on the producer that works in just the normal way

{{{
   public class SearchResultsProducer {
   private List<Person> results;
   public void setSearchResults(List<Person> results) {
      this.results = results;
   }
}
}}}


%%(color:red; font-weight:bold)Unresolved points: 1. Can we really get away with uninstantiable "fake" types? 2. There are risks with flows that reuse the same flow scope name with completely different kinds of values. Probably for RSF 0.8 and beyond, we might want some way to actually import the PRODUCERS into the flow scope as well, although this creates a portability risk wrt. the app. We face a portability risk the other way though as well, since we would not easily be able to host apps which had flow scope name collisions.%%


Another route that variables could get into flow scope is like this [[from {{search-flow.xml}}]:

{{{
  <subflow-state id="browseDetails" flow="detail-flow">
    <attribute-mapper>
      <input-mapper>
        <mapping source="requestParameters.id" target="id" from="string" to="long"/>
      </input-mapper>
    </attribute-mapper>
    <transition on="finish" to="displayResults"/>
  </subflow-state>
}}}

This corresponds to the "input" definition on {{detail-flow.xml}} like this:
{{{
  <input-mapper>
    <input-attribute name="id"/>
  </input-mapper>
}}}

Hopefully this treatment of *all* flow scope things is fairly uniform under the hood, and we would be able to treat them with a global inchuck which had no real opinion about their source (of which there may be some others in SWF we have not yet seen). One integration point this *does* raise though is the required validity of this expression {{source="requestParameters.id"}} which reminds us again of the requirement for this "fake parameter map" which is slightly uneasily bridging the world between ViewParameters and the SWF impression of the world. This is all mediated by the SWF {{RequestContext}} interface which will be one of our key points of customision. The main challenge with the integration will be juggling the apparent contents of, in particular, the request parameter map both on the render and action cycles so that the relevant expectations of RSF and SWF are maintained.

!Wrapping request parameters - back-reflection on SpringMVC integration
This is somewhat easier in SWF than in SpringMVC since the abstraction point is much more clearly defined - but having made this approach work in SWF, it might be possible to backport it to SpringMVC by using full Http/PortletRequestWrappers so that we could gain a slightly better idiom for UIInternalLinks than we currently have. At the moment RSF-SpringMVC integration in its current form could not be extended to PortletMVC since the interpretation of the UIInternalLink body is intended to be a raw "relative resource URL", of the sort we might see in the template, which needs only a URLRewriteSCR rewrite. This is obviously not correct in a Portlet (and hence actually not correct at all) - resource URLs live in a completely different space to view URLs.

Further thoughts on that... we don't really need/can use a ''wrapper'' for MVC - since MVC is stuck with the wrapper it has *directly* inherited from the container (although we could conceivably use a filter). But we perhaps need just a different kind of ViewParams for MVC apps, similar to the "raw-ish" SWFViewParams. The real key annoyance is giving SpringMVC a first-class idea of something like the "viewID", the key RSF resolution point - this is already done for us in SWF by the {{view="thing"}} declaration on a {{view-state}}. SpringMVC currently expects to resolve against views with UrlHandlerMappings, which nastily mix up the URL space between views and actions
{{{
  <bean id="urlMapping"
      class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
      <props>
        <prop key="/hello.htm">springappController</prop>
        <prop key="/priceincrease.htm">priceIncreaseForm</prop>
      </props>
    </property>
  </bean>
}}}
How does this work in PortletMVC? What is the meaning of the "key" when it is no longer a pathInfo String? Can it just be "forced" into yet another attribute in the way we do with RSFPortlet?

----
%%(color: #666666; font-family: sans-serif; font-size:80%)You can post comments and questions on this page using the following blog. Please set your name using [UserPreferences] before posting.%%
[{INSERT WeblogPlugin}]
[{INSERT WeblogEntryPlugin}]