myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Nick77 <>
Subject Best Practice Suggestions
Date Thu, 16 Nov 2006 17:23:11 GMT


I've been playing around with JSF recently, and having had some initial
problems with session-scoped beans, browser back button use and Javascript
submits, I'm posting some ideas for JSF Best Practices...

Separation of Model, View and Controller:
The Model is the 'backing' bean, 1 bean per JSP page, I'll call it the
ModelBean. Contains only the data that is required for display in the view,
and also id fields (the kind of things you'd put in a hidden input in
Struts). Also may contain presentation-specific logic e.g. calculating the
value to use for a rendered attribute, to keep lengthy EL expressions out of
the JSP.

The View is the JSP page (including the JSF component tree). Contains EL
expressions to 'bind' to ModelBean properties, and EL expressions to wire
actions and actionListeners to Controller methods.

The Controller is a separate bean, probably 1 bean per JSP page (maybe not
if you've got some common functionality in different pages). I'll call this
the ControllerBean. The ControllerBean handles events fired by View
components, e.g. action="#{controllerBean.updateCustomerDetails}" and then
calls the appropriate method in the Business Interface. The ControllerBean
has references to both the ModelBean and the Business Interface
implementation which are managed i.e. defined in faces-config.xml. Therefore
a typical user action such as clicking Update Customer Details will invoke
controllerBean.updateCustomerDetails, which will in turn extract any
user-entered data from the ModelBean, use this data as parameters to the
call to the Business Interface, and then depending on the result of that
call, populate the ModelBean with the results and invoke the desired
navigation by returning an appropriate String.

Minimal Bean Scope:
The ModelBean and ControllerBean are in request scope, the Business
Interface implementation is also a managed bean, but is in session scope.

Use t:saveState:
As everything is stateless, how do I ensure that the view has some notion of
the 'current' Customer? Also how do I handle use of the browser back button?
The answer is to use t:saveState to serialise the ModelBean along with the
component tree. That way, when submitting a page (e.g. Update Customer
Details) the ModelBean is not recreated, just de-serialized automatically by
t:saveState. It has non-null values for id, child Collections etc so no
nasty problems with dataTables and commandLinks.

Get rid of Javascript submit():
I wanted dependent drop-down lists, e.g. 2 list boxes, when you select from
the first one e.g. Shape/Colour, it updates the available choices in the
second one e.g. Square/Circle or Red/Green/Blue. Initially I used
onchange="submit()" so I could refresh the page with the new choices in the
second drop-down list. But I found this caused a problem if you use the
browser back button - go 'back' to this page then cause an onchange event -
in my implementation this caused the browser to go 'forward' in its history
cache. This was not the desired effect. So I used the method described 
http:// here  to
avoid the plain submit().

Advantages of the above:
Clear separation of concerns in the presentation layer (instead of combining
Model and Controller like most JSF examples I've seen).
Less use of session scope means less memory required on server and less to
worry about for session failover.
No problems with use of browser back button (assuming your Biz Interface can
deal with 'duplicate' invocations).

Increased processing to create/recreate request-scoped beans.
Increased processing, bandwidth and client memory required to use

This stuff may well be obvious to most people viewing this forum, so if you
think its obvious/rubbish/useful please let me know (and preferably why :-)
all comments/feedback welcome...


View this message in context:
Sent from the MyFaces - Users mailing list archive at

View raw message