Portable Portlet Development with RSF Antranig Basman, CARET, University of Cambridge Introducing RSF • What is it, Doctor?? RSF is a Java web programming framework, with roughly the same scope as Sun’s JSF – it takes care of: • Locating and rendering views • Managing server-side and client-side state • Handling and abstracting the request cycle It does NOT take care of: • What lies behind your data model (ORM) Hibernate & co are highly developed solutions to this which RSF aims to facilitate, not replace. Why (YET) another web framework? • There are now over two dozen open source Java web frameworks out there (many probably moribund/defunct) • Would properly need pretty good reason to create another • RSF grew out of work with JSF and preserves all of its key value points • JSF suffers from numerous architectural, practical and philosophical problems • Also, JSF is not adapted for lifecycles/environments typically found in academic institutional development – long maintenance lifetimes – perpetual reskinning/branding – interface aggregation/flexible delivery engines (accessibility vs. AJAX flashiness, thin/thick clients) RSF from JSF I • JSF core value points: – JSF is portable1 – can target the same code at portlet/servlet environments, – as well as different markup dialects – JSF features a bean line – communication from view layer to model is only via EL expressions, reflectively evaluating value bindings and method bindings *nearly* - after 3 years and despite both being Sun standards, JSF JSR-168 integration is still incomplete (portal modes &c) 1 RSF from JSF II • JSF core deficits: – Neither JSF inputs nor outputs are any kind of XML (by default crummy taglibs as input, halfassed, Javascript-laden HTML as output) – Does not properly separate logic from presentation (even with Facelets, input “templates” contain iteration and model logic and are NOT safe to give to designers) – Makes heavyweight use of session state, destroys server efficiency, breaks URL idioms and browser forking RSF from JSF III • JSF core deficits II – Lack of support for many core pieces of the browser idiom (bookmarkability, back button, browser forking, POST->GET, GET forms &c &c) – Fragile request lifecycle (“Phase” system) behaves erratically in presence of exceptions, is generally monolithic and uncontrollable – IoC integration is at best awkward (JSF-Spring) – Is simply in general a pain to work with – taglibs are hard to write, framework is highly intrusive, stateful and heavyweight (FacesContext) – Could go on much longer! (see RSF wiki) Architectural Snapshots #1: JSF Haunted House • Designed on a grand scale • Lots of thought to architecture, ambitious reach • Large, complex • Lots of strange noises and inexplicable phenomena Quick Recap of RSF Points • The key RSF features are: – Pure (REALLY pure) HTML templating – Zero server state processing – Built ENTIRELY of a set of Spring contexts, rather than merely “integrating” with Spring – Request-scope IoC container, RSAC – RSAC leads to straightforward and slick integration even with extremely peculiar environments (JSR-168, Cocoon, Hibernate, Sakai are all in the bag – IChannel is coming) • Integrations are always only a few hundred LOC • JSF JSR-168 is thousands RSF compared to JSF • RSF preserves all the “key value points” of JSF – Abstract “component tree” isolates you from view technology – EL bindings system isolates the data model from the view layer – Abstract dispatching procedure isolates you from the hosting environment (Servlets, Portlets, Sakai – IChannel?) • But delivers on all its promises and more – – – – – Free of “model” classes coupling you to the framework “Speak like a native” approach to HTML – anything is possible Test your UI in the filesystem, full previewability Output is GUARANTEED valid XML IoC throughout the framework means application fragility does not increase with size, testability &c. State in RSF • The key difference for folks coming from JSF is that RSF holds zero server state by default • Not only the component tree, but also the entire client model are thrown away at the end of every request • Server resource are precious, and the “time between requests” for a particular user is very large in server terms – why keep around something you could easily regenerate (your app has its own model)? • A better fit for HTTP which is a stateless protocol. RSF apps are very URL-response, and much more amenable to HTTP tools such as caches, proxies &c Case Study I : Sakai TaskList App • Part of the Sakai “Programmers’ Cafe” exercise at Sakai Vancouver Conference June 2006 • The simplest app that could be useful • Demonstrates most of the key requirements on a Sakai app – ORM using standard Sakai SessionFactory (as well as other approaches, abstracted behind a DAO interface) – Rendering compliant with Sakai Style Guide – Exposing a Sakai-wide service API • Written in JSF – Easily the most problematic aspect of the whole tool JSF Tasklist App Structure TaskList.jsp TaskListBean.java DataModel TaskListServiceImpl.java TaskListService.java TaskBeanWrapper.java TaskList.java TaskListManager.java Thinking • Looking at the TaskListService API in detail, it becomes clear that it only really has value *within* the app • This API was created because it is awkward to deliver enough of the Sakai and other Spring dependencies to a JSF-managed bean • This API and Impl can be destroyed completely in the RSF version • We know that in the RSF version, the view logic in the JSP will be placed into a ViewProducer, TaskListProducer • The ViewProducer is *already* a Spring-configured bean, so the dependencies which used to be delivered to TaskListServiceImpl will be transferred onto TaskListProducer • Since the Producer is normal Java code which has full access to the application state, the “Wrapper” class is also unnecessary. • The presence of the DataModel in what should be the business layer of the app was an unconditional excrescence. JSF Tasklist App Structure 2 TaskList.jsp TaskListBean.java DataModel TaskListServiceImpl.java TaskListService.java TaskBeanWrapper.java TaskList.java TaskListManager.java RSF Tasklist App Structure TaskList.html TaskListProducer.java TaskListBean.java TaskListManager.java TaskList.java It doesn’t stop there • RSF ORM “idiom” rather than “library” • OTP (= “One True Path”) assigns unique EL path to each entity of data model • RSF “EL” is slimmed down so much (only elementary reads/writes permitted) that it is safe to address arbitrarily nasty “POJO” models, even those managed by Hibernate • Abolition of “DAO”s RSF Tasklist App Structure with OTP TaskList.html TaskListProducer.java TaskListBean.java TaskListManager.java TaskList.java Result: • A Sakai app free of ANY SAKAI CODE • A Hibernate app free of ANY HIBERNATE CODE • Pure HTML templating makes app effortlessly reskinnable by anyone armed with a copy of Dreamweaver • Portable to any environment (where the functionality is relevant) – could become a JSR-168 app with no code changes • This is impossible with any other framework NB – could have tried this with interfaces, but this tends to create a fragile design – need to anticipate all design points up front, rather than “abstraction on demand” through requestscope IoC. This approach leads to defining an entire “abstraction platform” covering all cases with “kitchen-sink” type interfaces. Case Study II: Spring MVC “Step by Step” Product sample • Thomas Risberg’s very useful walkthrough of a SpringMVC app http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html • SpringMVC is worthy but modest • Hampered by “Lowest Common Denominator” of existing view technologies • Spring philosophy of “work what what is there already, do not implement” • Is NOT portable (Servlet and Portlet packages are named similarly, but are not interchangeable) Architectural Snapshots #2: SpringMVC Bungalow • Modest, competent • Works fairly well for everyone • Doesn’t get you very high off the ground (in terms of abstraction) 1. SpringMVC integration • The IKAT renderer from RSF has been ported to SpringMVC • Can be used as “just another SpringMVC rendering technology”, along with Velocity, FreeMarker and JSPs • Creates some duplication (Controllers/Producers), but highly useful for making reskinnable apps • “Step by Step” rewritten with drop-in replacement for JSPs, no other code changed • Resulting app is reskinnable, but still not portable 2. SpringMVC replacement • Entire app rewritten using RSF • Much code disappears, increased level of abstraction • Preserves ALL non-SpringMVC code with no changes – Business model/“manager” – DAOs – Spring Validation • Resulting app *IS* portable to JSR-168, as a result of destroying SpringMVC “Controller” layer • Not only is the Controller unit testable, but the renderer is as well!! First closed-loop UI testing. RSF and AJAX • Everyone talks about this, so I’d better • Since RSF preserves complete autonomy on the client (*pure* HTML templates), all native clientside AJAX libraries integrate naturally – no need for AJAX “components” in the framework • Lots of success with – Prototype.js – Script.aculo.us – Rico • RSF renderer is markup agnostic, no problem rendering XML for AJAX tables (Rico), HTML fragments for divs (Ajax.Update) or full pages with embedded AJAX calls. • Ask Steve Githens (on the RSF forums) RSF Timeline July 2005 “JSFUtil” destroyed September 2005 RSF 0.5 demonstrated at Developers’ Meeting, Cambridge – UIOutput and UIInput only December 2005 RSF 0.6 – UIType system stabilised, Flow “Lite” April 2006 RSF 0.6.1 – Reformed build system, Hibernate support, full XML component serialisability, UISelect – First public release, JIRA, forums May 2006 RSF 0.6.3 – Complete set of HTML components, non-HTML ContentTypes (XUL, RSS, AJAX), JSR-168 August 2006 RSF 0.6.4 – SpringMVC integration, support for Sakai 2.2, Hibernate 3 (IChannel?). Last 0.6 release September 2006 RSF 0.7 – Multi-file templates, custom components, “Renderer reform” Early 2007 RSF 1.0 – General shakedown, acceptance testing, load testing, beginnings of GWT-style integration The future RSF 2.0 – AutoAJAX, Differential IKAT and the Bean Invalidation Model…. leading to “Snooze” Acknowledgements The CARET Team Raymond Chan Andrew Thornton Dan Sheppard Ian Boston and John Norman RSF http://www2.caret.cam.ac.uk/rsfwiki