Title: RSF Programmers
1RSF Programmers CaféandORM in Sakai with RSF
and Hibernate
- Antranig Basman,
- CARET, University of Cambridge
2Quick 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
3RSF 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 - Output is GUARANTEED valid XML
- IoC throughout the framework means application
fragility does not increase with size,
testability c.
4Café TaskList app
- 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
5JSF Tasklist App Structure
TaskList.jsp
TaskListServiceImpl.java
TaskListBean.java
TaskListService.java
TaskListManager.java
DataModel
TaskBeanWrapper.java
TaskList.java
6Thinking
- 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.
7JSF Tasklist App Structure 2
TaskList.jsp
TaskListServiceImpl.java
TaskListBean.java
TaskListService.java
TaskListManager.java
DataModel
TaskBeanWrapper.java
TaskList.java
8RSF Tasklist App Structure
TaskList.html
TaskListProducer.java
TaskListBean.java
TaskListManager.java
TaskList.java
9Timeline 1
- Run the JSF app, and save the HTML it produces
(take a look at this as TaskList-originalJSF.html)
- Clean up the HTML (considerably) and annotate
with rsfid - Take faces-config.xml and convert into the
equivalent Spring declarations - Message bundle -gt Spring MessageSource (remember
to convert . to / in path) - TaskListBean.java -gt RSAC requestContext.xml
- NavigationCase -gt return from TaskListProducer
10Timeline 2
- Deal with web.xml
- Spring listener declaration is unchanged
- FacesServlet -gt ReasonableSakaiServlet
- Remove JSF context params
- Add RSF context param resourceurlbase context
name - Alter Sakai Request Filter mapping to ONLY apply
to path faces/ (no flexibility here with current
SakaiRSF but who cares noone should see tool
URLs anyway)
11Timeline 3
- Deal with project.xml
- A mess, as with all Maven stuff
- Basically, remove JSF dependencies (JSF and
commons-X stuff) and add RSF dependencies
(Spring, CGLib, XPP, ServletUtil and
PonderUtilCore) - NB this project does not use Sakai master project
but has hard-coded version numbers
12Timeline 4
- Write the ViewProducer!
- In this case, virtually all the logic ended up in
this file. - Made more sense to inject most leaf
dependencies into the TaskListBean (e.g. siteId) - This isnt quite the expected effect, since all
this code actually has framework dependence - But there is much less of it in total, and what
there is is more straightforward - And in truth this actually is view logic. There
is just a lot less business logic in this app
than appears at first sight. - Talk about LocaleGetter
13ORM with RSF (OTP style)
- This app used Hibernate ORM, but did not use the
RSFHibernate integration library - Demonstrates the broad church approach of RSF
- Basically, if it a Spring bean already, you can
just use it in RSF without any problems - RSF ORM enables us to destroy yet more code from
this app.
14RSF Tasklist App Structure with OTP
TaskList.html
TaskListProducer.java
TaskListBean.java
TaskListManager.java
TaskList.java
15Nearly
- Actually TaskListManager is serving a dual
purpose in our refactored RSF app - Not only is it the apps interface to its
storage, it is also Sakais interface to the app - This only happens because the app is essentially
just a CRUD app. For more complex apps these
interfaces would diverge. - RSF only lets you get rid of internal APIs, not
external ones! - So in fact we would need to preserve
TaskListManager for this app for its external
function
16Transit Beans
- Also, this app does indeed contain one line of
actual business logic.
if (newtask.getTask() null
newtask.getTask().equals("")) return
"error"
- This is essentially validation logic. In RSF,
this belongs in Transit Beans - A POJO with a setter, and a getter, which throws
an exception if value is invalid. - Use request-scope IoC to wire it into the setter
chain
17How does RSF OTP work?
- Assigns a unique EL path to each Entity managed
by ORM - This is why returning a Map from the RSF version
of TaskListManager is the beginning of OTP - The EL path for the TaskList with Id of 5 is
TaskList.5 - Add new entities with the special id form
TaskList.new 1 - Issue special binding type (UIDeletionBinding) to
unlink or delete an existing entity - If the request concludes normally, commit if
any kind of exception propagates out, rollback
18OTP result
- The TaskListBean disappears entirely!!
- TaskListManager disappears entirely (except for
external function) - Issue We cant do this in RSF right now, since
there is no deletion binding form for issuing
multiple deletes - Will be fixed in RSF 0.6.4
19Working example HibernateCookbook
- Look at javacategory version at
http//www2.caret.cam.ac.uk/rsfwiki/Wiki.jsp?page
HibernateCookBook_4 - Syntax for a Command link operating a deletion
binding
UICommand destroy UICommand.make(reciperow,
"recipe-destroy") destroy.parameters.add(
new UIDeletionBinding("Recipe." id ""))
- Isnt this cool?
- Brings Java that much closer to the convention
over configuration scriptaculous scumbag crowd
20What OTP requires
- If you have your own SessionFactory, just point
RSF at it and it will manage all the entities in
it - By default, just define a bean called
sessionFactory - If you are sharing a SessionFactory (e.g. Sakai
GlobalSessionFactory), need to list the entities
you want managed - You dont have to use Hibernate to use OTP All
thats required is - An AlterationWrapper to enclose the action
logic which needs to be transactional - A set of BeanLocators which expose the entities
at their root paths
21Takehome Message
- There will always need to be external APIs
- But internally you can do away with boring DAOs
and action beans, for all basic CRUD
functionality - For some apps, the external API is as wide as the
data model, so this is not so much benefit - OTP is just another RSF design option, the first
version of the app worked just fine and was
probably quite enough of an improvement on the
JSF version. - If you are still dealing with Hibernate under the
covers, you still need to watch out!