|
From: Boyce, K. G. <Kei...@bc...> - 2005-05-02 14:04:31
|
Sound's pretty comprehensive to me.=0D Has any thought been given to portlet integration supported by webflow?=0D Also as I understand jsf when you show a jsf view the view is a jsp rather than a url that is mapped to a jsp page. What are your thoughts on these issues?=0D Finally some work is being done on a taglib for Spring similar to struts taglib. Are there any interactions that need to be considered here (for instance if both jsf and spring taglibs are together on a single jsp? Garry -----Original Message----- From: spr...@li... [mailto:spr...@li...] On Behalf Of Craig McClanahan Sent: Monday, May 02, 2005 1:56 AM To: Spring Framework Developers Subject: [Springframework-developer] [webflow] JavaServer Faces Integration -- Proposed Requirements and Approach Sorry for a later initial post than I had intended -- life is never as calm as one would hope. I'd like to use this message to kick off discussions around a high quality integration of Spring WebFlow with JavaServer Faces, which I will also volunteer to help build and maintain, and then contribute into the Spring source code base so that everyone can benefit from it. As background for understanding what is required to accomplish this, I have implemented a relatively simple "dialog" mechanism (heavily inspired by SWF) into Shale -- my next generation web application framework that is built on top of JSF's extensible front controller facilities (rather than treating JSF as just a view tier technology).=0D I would like to briefly explain what I've done there, and use it to motivate further discussion about what the requirements for SWF-JSF integration should be, and some proposed solutions based on what I've learned so far. However, I'm definitely going to need assistance from Keith, Erwin, and others that are MUCH more familiar with Spring and SWF than I am :-) BACKGROUND - SHALE DIALOGS Shale is a next generation web framework that I proposed to the Struts community as "the architecture for Struts 2.x". It did not get accepted (by the other developers) as that, but it *did* get accepted as a formal Struts subproject so that it can share the community already built up around Struts, and attempt to build a community of its own. The starting point for information about Shale is the wiki page on it: http://wiki.apache.org/struts/StrutsShale Shale is (AFAIK so far) unique among Java-based web application frameworks in that it is designed *assuming* that JavaServer Faces front controller facilities will be used, rather than treating JSF as just a view tier technology (where there are integrations with many web frameworks already, including Spring MVC and Struts 1.x). This assumption, as it turns out, leads to dramatically less work to do as a framework developer -- there's a lot of beef already in existence, plus pluggability extension points that allow a fully featured framework to be built around the core of what JSF 1.x supplies. In turn, that has let me focus on providing value add features on top of the bare bones controller capabilities in JSF already. One primary motivation was implementing the "view helper" design pattern (also popularized in the application model that Visual Studio supports for ASP.NET and VB.NET applications), epitomized here in the ViewController interface. This particular pattern is synergistic with the dialog support discussed below, because it tends to reduce the number of action states required, but that's really not the focus of ths particular discussion. On my original set of goals for Shale was support for "dialogs" -- interactions with the user that were "longer than a request, but shorter than a session". I had made some initial clumsy attempts at adding a JSF flavor around this idea. Principally, that meant sharing a JSF "backing bean" (the Java code where you put event handlers associated with a page) between all the pages of a particular dialog.=0D It worked, but it was pretty clumsy. Then, I had started hearing about SWF, and got the chance to see Keith's presentation of it at TSSJS in Las Vegas last March. It was obviously a *much* better approach, so I set about learning what I could about it. I tend to learn by doing, so I created a fairly simple implementation of the same concept in Shale, but kept the name "dialog" (so that "flow" would be available when SWF was eventually integrated :-). The dialog support is in package "org.apache.shale.dialog" of the core library -- and doesn't actually have any dependencies on other parts of Shale, although applications will benefit if they take advantage of those. The "use cases" example app uses this facility in the "org.apache.shale.usecases.profile" package where two dialogs (Log On and Edit Profile) are used. The package Javadocs for this package include state diagrams for these two dialogs (if you've read the SWF "Practical Guide" page, you'll know exactly how this translates to dialog definitions ;-). Compared to SWF, dialogs are different in the following ways: * Action states are encapsulated as a JSF "method binding expression", which is an EL expression pointing at a public method of some bean (typicaly a JSF managed bean) that takes no arguments and returns a String that is interpreted as the outcome that drives the next transition. This method signature happens to match the signature used for an "action" that is invoked by a JSF command component (such as a submit button), and JSF already provides the expression evaluation machinery, so it was natural to support a familiar approach. * View states are encapsulated as the rendering of a JSF-based response, *plus* the processing (through the normal JSF request processing lifecycle) of the subsequent submit. The logical outcome string returned by the submit action that was ultimately invoked drives the transition from the view state to the subsequent state within this dialog. * A facility is provided such that the state information specific to a particular dialog may be exposed (as a property on a session scoped bean) but automatically cleaned up when the dialog completes. This is done by calling setData(Object) on the Status instance (in session scope) where the dialog facility keeps track of the current state of the dialog being executed. This "data" object is pushed onto a stack when a nested dialog is entered, and popped off when the dialog is completed -- which means the application does not need to be concerned with throwing away a session scope attribute when the outermost dialog is finished. * As a happy consequence of the above feature, pages containing JSF components can use value binding expressions to store information in this data object, without any regard to which dialog is being executed (or how deeply nested it is). In the Shale sample application, the "Edit Profile" dialog has a "fullName" field that is bound to a property of the local state object like this: <h:inputText id=3D"fullName" value=3D"#{dialog.data.fullName}"/> where "dialog" is the session scoped bean containing the state of the dialog computation, and "data" is the general property a dialog can use to store state specific to this dialog. The state object will be thrown away for you when the dialog completes -- essentially creating a "transaction scope" even though no such thing is (yet) supported by the Servlet API. * (Recently added) it is possible to define transitions that are global to an entire dialog, rather than having to explicitly define them all inside a state definition. This is exactly analogous to the way that Struts allows you to define global <forward> elements (for the entire application) that can get overridden on a per-action basis by a local <forward> element. The idea of configuring dialogs and using these facilities works out quite well ("well, duh" says anyone already familiar with SWF :-). It also turned out to be incredibly simple to implement -- one of the JSF extension points is the NavigationHandler API, which the framework invokes after the application action returns. It is used to drive navigation to another page (or back to the same page, if the logical outcome is null). The key method signature is: public void handeNavigation(FacesContext context, String fromAction, String outcome); where "context" is an encapsulation of the state of the current request, "fromAction" lets you distinguish between submit buttons (that might return the same outcome) on the same form, and "outcome" is the logical outcome that is returned by the action method. By default, JSF supplies a mechanism that analyzes a set of navigation rules (defined in a faces-config.xml file) to choose the next view (typically a JSP page, but that's by no means the only option) to be rendered. However, this is an extension point where a framework can provide value added facilities, or delegate to the standard machinery if it wants to. As currently implemented in Shale, the custom NavigationHandler provides the following facilities: * When no dialog is being executed, delegate to the standard JSF NavigationHandler implementation (so that everything the developer knows about JSF navigation happens as expected). * A dialog named "xxx" is entered when an action returns a logical outcome of "dialog:xxx". This approach required no change to any JSF (or JSF-called) APIs -- it's just a specialized interpretation of the logical outcome string. * Once a dialog is entered, state transitions are managed by the custom NavigationHandler implementation (org.apache.shale.dialog.faces.DialogNavigationHandler) in a manner very similar to what a SWF Controller does. This includes the ability to nest dialogs (just like SWF can nest flows). The end result is an environment with some very important benefits resulting: * Outside of the dialogs world, standard JSF things work in the usual way. * Dialogs can reuse actions and view states (including those that are also accessed directly via standard JSF facilities), because the interpretation of the logical outcome is specialized per dialog. * As with SWF, the configuration of a dialog (or a flow) is very much amenable to tool-aided support like graphical drag-n-drop development of the overall flow -- as well as for more formal UML-based tool support. * Because of the other capabilities provided by Shale, an application will typically need fewer "setup" action states (because the prerender() method of a ViewController can take many of these responsibilities) and less work in what is typically a "bindAndValidate" action in Spring (because JSF has its own support for validation processing that preceeds such a state). But these are just icing on the cake -- the key values of having managed dialogs are independent of Shale. PROPOSED SWF-JSF INTEGRATION REQUIREMENTS Given what I've learned from the above investigations, then, I'd like to propose the following as requirements to be met by an integration between SWF and JSF: * When a flow is *not* being exected, all the standard JSF navigation capabilities will work as expected. * Execution of a JSF action method can cause a SWF flow to be entered, by returning a suitably encoded logical outcome (perhaps "flow:xxx" or "swf:xxx" to invoke a flow named "xxx"). In addition, other standard approaches to entering a flow will also work, of course. * Zero or more flows may reuse the same JSF pages (and backing beans). This implies that the flow management facility will take over the interpretation of logical outcomes from standard JSF action methods, which would otherwise drive the standard navigation facilities of JSF. * There should be a mechanism to push a local state object onto a stack, and have it popped off on dialog completion (as Shale does) so that applications do not have to worry about it. This is not mission critical (and indeed there might be facilities for this already that I haven't discovered yet :-), but it is very important to usability. * JSF applications using SWF must be able to leverage all of the sophisticated transition management capabilities that SWF supports (as opposed to the simple deterministic model that Shale currently provides). * When executing a flow, a JSF view state will cause the corresponding JSF view to be rendered, *and* the flow will be suspended until the subsequent JSF form submit occurs. The logical outcome from the action method that is invoked for the appropriate submit button will be used to drive the next transition. - IMPLICATION: If JSF validation failures occur, the current page will be redisplayed without ever invoking the application action method; implying that the current state will remain the same. This is typically the desired result, but requires no explicit transition management in a JSF-based application. * While executing a flow, non-JSF view states should be supported as well (this probably comes out of the box, but it needs to be called out). PROPOSED IMPLEMENTATION APPROACH: Here's where I really need some help from you guys :-). It seems that all of the above requirements can be met, in a manner fairly similar to what I did with Shale's dialogs, by implementing a custom JSF NavigationHandler with the following features: * When not currently executing a flow, standard JSF navigation is performed. * When a logical outcome of the form "flow:xxx" is handed to the handleNavigation() method, the flow named "xxx" is invoked at its start state. * While a flow is invoking action and subflow states, the usual SWF processing will occur. * When a flow invokes a view state for a non-JSF page, the usual SWF processing will occur. * When a flow invokes a view state for a JSF page, the appropriate JSF incantations to create the corresponding view, and render it, will be invoked.=0D Further, the state of this flow will be suspended until JSF processes a subsequent form submit, and invokes an application action that returns a logical outcome. This outcome will be the one used to drive a transition from the current view state to some other state in the current flow (or exiting the flow, if this is also an end state). * I don't see anything like this in the current APIs (but that doesn't mean it doesn't exist :-), but it would be very useful to be able to push and pop the current model data for a flow in a manner similar to what Shale does. In particular, this facilitates the use of JSF value binding expressions that have a constant content regardless of nested flow execution. * The implementation should be packaged in a JAR file that contains a "META-INF/faces-config.xml" resource that automatically configures the integration with JSF, with no required changes to web.xml (I can help you accomplish the same for the existing JSF managed bean integration as well). Does this sound compatible with what you guys have had in mind for SWF? Craig McClanahan ------------------------------------------------------- This SF.Net email is sponsored by: NEC IT Guy Games. Get your fingers limbered up and give it your best shot. 4 great events, 4 opportunities to win big! Highest score wins.NEC IT Guy Games. Play to win an NEC 61 plasma display. Visit http://www.necitguy.com/?r _______________________________________________ Springframework-developer mailing list Spr...@li... https://lists.sourceforge.net/lists/listinfo/springframework-developer This message is a PRIVATE communication. If you are not the intended recipient, please do not read, copy, or use it, and do not disclose it to others. Please notify the sender of the delivery error by replying to this message, and then delete it from your system. Thank you. |