December 17th, 2009
5:12 pm
Correct Scoping/Separation of JSF Managed Beans

Posted under JSF
Tags , ,

This ICEfaces article details the importance of the correct separation of concerns and scoping of JSF managed bean. Of particular importance is ensuring that you do not mix up the layers of the MVC design pattern, by mashing up different MVC concerns into a single managed bean. Correct splitting up of classes and scoping can avoid this and achieve the desired loose coupling.

The approach I have taken, which differs subtly from the above article but is fundamentally the same, is as follows :-

  1. I encapsulate all calls to the business/service layer in a ModelBean. This bean exposes properties which hold all the business data fetched from the service layer, and various populate and save methods to fetch/populate those properties and finally persist modified versions of them back via the service layer. As I am using JPA and have generally elected not to use the DTO pattern,  the properties  are JPA entities, objects which are the result of JPA select constructor expressions, or primitive data values from the database. For clarity, the ModelBean is stateful and session scoped and so holds the properties all the time a page is being viewed/edited, whereas all the calls to the service layer are stateless. I might have a single model bean, or I might break it down into a number of separate beans, depending on what suits the design. Whilst there could be one per JSF page, typically I find that there is scope for a lot of re-use of common methods and properties acrosss pages. Conversely, for a larger application, it may become unmodular and unwieldy to have a single model bean. A fundamental point about this bean is that it does not  perform any controller logic, i.e. does not directly interact with the components on the page (although typically of course they will refer to its properties to get data).
  2. I encapsulate all the logic which interacts with the components on the page in a controller bean for the page. Where the page contains subcomponents such as custom facelets tags (in my case, a TablePair tag is an example of this), I typically find that a good design is to have a separate child controller bean for each custom component, so that the controller mirrors the structure and requirements of the view. These controller beans do not access the business/service layer directly – all such access is routed via the ModelBean above. This separates all code which is directly aware of the business layer interface from controller code which is aware of the structure and handling of the page.
  3. I ensure that the view (the JSF page, facelets and tags) does not contain any business or controller logic. As this post indicates in its last paragraph, the presence of logic expressions in JSF value expressions is often a warning bell that this may have occurred, and the view has been polluted with controller or model concerns. For example, the disable attribute on a JSF component is strictly a property reference to an enable/disable property in a controller bean. The conditions under which that property is enabled or disabled are strictly a controller issue. The above post also details design guidelines for state change management and event handling and propagation for the controller bean.

 

A good test of the design is to ask yourself the following questions:-

  1. What would need to change if the call interface to the service layer changed? Would it be necessary to change any backing beans which also contain controller logic – which handle components on the page? If so, the design has become polluted. Consider a possible requirement where the service layer interface was enhanced, and the old interface was eventually due to be deprecated. You might have a situation where you needed to support both versions. Would this result in having 2 identical copies of some controller code which interacts with components on the page? If so, you have polluted the design and mixed controller concerns in with the model. If you had to perform any bug fixes on the duplicated controller code, you would have to update both copies identically to keep them in step, and so have broken modularity.
  2. Conversely, what would need to change if the user interface to the page changed, but performed the same functions in terms of the model (perhaps the interface was improved to make it more user friendly)? Would it be necessary to change any beans which contain calls to the business/service layer? If so, the design has again become polluted. Consider a possible requirement where you needed to maintain both the old and the new versions of the user interface for a period until the old one had been completely phased out. This would require 2 versions of the controller beans to be maintained. Would this result in having 2 identical copies of some model code which directly calls the business/service layer? If so, you have polluted the design and mixed model concerns in with the controller. If you had to perform any bug fixes on the duplicated model code, you would have to update both copies identically to keep them in step, and so have broken modularity.

Comments Off on Correct Scoping/Separation of JSF Managed Beans