JSF backing bean structure (best practices)
Asked Answered
C

6

121

I hope that in this post, I can get people's opinions on best practices for the interface between JSF pages and backing beans.

One thing that I never can settle on is the structure of my backing beans. Furthermore, I have never found a good article on the subject.

What properties belong on which backing beans? When is it appropriate to add more properties to a given bean as opposed to creating a new bean and adding the properties onto it? For simple applications, does it make sense to just have a single backing bean for the whole page, considering the complexity involved with injecting one bean into another? Should the backing bean contain any actual business logic, or should it strictly contain data?

Feel free to answer these questions and any others that may come up.


As for reducing coupling between the JSF page and the backing bean, I never allow the JSF page to access any backing bean property's properties. For example, I never allow something such as:

<h:outputText value="#{myBean.anObject.anObjectProperty}" />

I always require something like:

<h:outputText value="#{myBean.theObjectProperty}" />

with a backing bean value of:

public String getTheObjectProperty()
{
    return anObject.getAnObjectProperty();
}

When I loop over a collection, I use a wrapper class to avoid drilling down into an object in a data table, for instance.

In general, this approach feels "right" to me. It avoids any coupling between the view and the data. Please correct me if I'm wrong.

Conflict answered 14/4, 2009 at 1:51 Comment(2)
Can you given an example for: When I loop over a collection, I use a wrapper class to avoid drilling down into an object in a data table, for instance.Psychomotor
For more information, see BalusC's answer at #7223555Conflict
W
147

You might want to check this out: making distinctions between different kinds of JSF managed beans.

Here is a description of the different bean types, as defined in the above article by Neil Griffin:

  • Model Managed-Bean: Normally session scope. This type of managed-bean participates in the "Model" concern of the MVC design pattern. When you see the word "model" -- think DATA. A JSF model-bean should be a POJO that follows the JavaBean design pattern with getters/setters encapsulating properties. The most common use case for a model bean is to be a database entity, or to simply represent a set of rows from the result set of a database query.
  • Backing Managed-Bean: Normally request scope. This type of managed-bean participates in the "View" concern of the MVC design pattern. The purpose of a backing-bean is to support UI logic, and has a 1::1 relationship with a JSF view, or a JSF form in a Facelet composition. Although it typically has JavaBean-style properties with associated getters/setters, these are properties of the View -- not of the underlying application data model. JSF backing-beans may also have JSF actionListener and valueChangeListener methods.
  • Controller Managed-Bean: Normally request scope. This type of managed-bean participates in the "Controller" concern of the MVC design pattern. The purpose of a controller bean is to execute some kind of business logic and return a navigation outcome to the JSF navigation-handler. JSF controller-beans typically have JSF action methods (and not actionListener methods).
  • Support Managed-Bean: Normally session or application scope. This type of bean "supports" one or more views in the "View" concern of the MVC design pattern. The typical use case is supplying an ArrayList to JSF h:selectOneMenu drop-down lists that appear in more than one JSF view. If the data in the dropdown lists is particular to the user, then the bean would be kept in session scope. However, if the data applies to all users (such as a dropdown lists of provinces), then the bean would be kept in application scope, so that it can be cached for all users.
  • Utility Managed-Bean: Normally application scope. This type of bean provides some type of "utility" function to one or more JSF views. A good example of this might be a FileUpload bean that can be reused in multiple web applications.
Wherewith answered 23/6, 2009 at 1:21 Comment(7)
This is a great article. I have never seen it before and am definitely glad that you posted it. Whoever voted this down is crazy. It's not iceFaces specific.Conflict
Link to actual article appears to be gone.Maramarabel
A copy can be found hereArruda
Still, I can't get to it that this answer is currently at 71 upvotes. Whoever implemented their JSF application according those rules must undoubtedly afterwards be ranting on JSF being a terribly opaque framework and their JSF applications being a big code mess and they all blame JSF itself instead of their own bad approach based on the wrong lessons and so-called "best practices" learnt.Joyless
is any of these beans' logic executed in the browser instead of in the server?Gaw
@Joyless care to explain what the correct approach to JSF should be like then?Moshe
@Ghos3t: see link which OP itself posted in question's comments.Joyless
C
14

Great question. I suffered a lot with the same dilemma when I moved to JSF. It really depends on your application. I'm from the Java EE world so I would recommend to have as little business logic in your backing beans as possible. If the logic is purely related to the presentation of your page, then it is fine to have it in the backing bean.

I believe one of the (many) strengths of JSF is actually the fact that you can expose domain objects directly on the managed beans. I would therefore strongly recommend the <:outputText value="#{myBean.anObject.anObjectProperty}" /> approach, otherwise you end up making too much work for yourself in manually exposing each property. Furthermore it would be a bit of a mess when inserting or updating data if you encapsulated all the properties. There are situations where a single domain object may not be sufficient. In those cases I prepare a ValueObject before exposing it on the bean.

EDIT: Actually, if you are going to encapsulate every object property that you want to expose, I would recommend that you instead bind UI components to the backing bean and then inject the content directly into the value of the component.

In terms of bean structure the turning point for me was when I forcefully ignored all the stuff I knew about building web applications and started treating it as a GUI application instead. JSF mimics Swing a lot and therefore the best practices for developing Swing applications would mostly also apply to building JSF applications.

Carven answered 14/4, 2009 at 21:4 Comment(1)
Thanks for your insight. I never really did much in the way of swing applications (other than academic projects a long time ago). What are some good principles of swing applications? Also, why is it a mess when inserting and updating values? seems the same to me?Conflict
P
5

I think the most important thing with your backing beans is to seperate their logics. If you have a front page for a CMS system I would see it as bad practice to put every piece of code into one bean because:

  1. The bean would turn very large eventually
  2. Its easier for other people to find what their looking for if they are troubleshooting the login page, if they then can easily just look up the loginBean.java file.
  3. Sometimes you have small pieces of functionality that is clearly distinct from the rest of your code, by separating this I would imagine you would make it easier on yourself to redevelop/expand this code into something bigger, when you already have a nice bean with good structure.
  4. Having 1 big bean, to do it all, will make it more memory dependant if/when you have to do declarations like this MyBigBean bigBean = new MyBigBean(); instead of using the funksjonality you actually needed by doing LoginBean loginBean = new LoginBean(); (Correct me if Im wrong here???)
  5. In my opinion, separating your beans is like separating your methods. You dont want 1 big method which runs over 100's of lines, but rather split it up with new methods that handles their specific task.
  6. Remember, most likely someone other than you will have to work on your JSF projects aswell.


As for the coupling, I dont see it as a troublesome issue to allow your JSF pages access too the properties in objects in your backingbean. This is support which is built into JSF, and really just makes it easier to read and build imo. Your allready separating the MVC logic strictly. By doing this your saving yourself tons of lines with getters and setters in your backingbean. For example I have a really huge object given to me by the web services, where I need to use some properties in my presentation. If I were to make a getter/setter for each property my bean would expand with atleast 100 more lines of variables and methods for getting the propeties. By using the built in JSF functionality my time and precious code lines are spared.

Just my 2 cents regarding this even with the question already marked as answered.

Powerhouse answered 16/4, 2009 at 7:58 Comment(2)
however, if you have a huge object that's sitting in your bean, and you have -- say -- 15 EL functions digging into that object from the JSF page, you are now tied not only to the bean, but to that object. Therefore it will be difficult to remove that object without breaking the UI.Conflict
But wont your backing bean be tied to that object aswell? And your UI tied to the backing bean? When you then have to modify it, you will have to change all your getters/setters in both UI and bean.Powerhouse
C
4

I might not answer your every question, because few seems quite dependent on case to case.

  • This is fine to have a business logic in your backing bean. It depends where are you coming from. If you are practicing domain driven design, you will be tempted to include the business logic in to backing bean or may be persistence logic as well. They argue that why so dumb object. Object should carry not just state but behavior too. On the other hand if you consider traditional Java EE way of doing things, you might be feeling like having data in your backing bean, which also can be your entity bean, and other business and persistence logic in some session bean or something. That is fine too.

  • Its perfectly fine to have single backing bean for the whole page. I don't see any problem with this alone. This might not look right, but that depends on the case.

  • Your other question is far more dependent on case you are having in hand. I would prefer to go domain driven here, it might be appropriate to add properties to the existing or otherwise create a new bean for that. Which ever suits better. I don't think there is any silver bullet for this.

  • Which properties belongs to which backing bean. Well, is it not depend on the domain object? Or may be the question is not that clear.

Moreover, in your given code example, I am not seeing any huge benefit.

Caucasoid answered 14/4, 2009 at 3:20 Comment(2)
if--for example--we were to change from using home-brewed POJOs created with JDBC queries, to Hibernate entities that had slightly different field names, we would have to not only change the backing bean. We would have to change the JSF page also. Not so with my code example. Just change the bean.Conflict
In that case you can make your backing beans, entities. then you just need to change the JSF pages. Or it depends why would you change the name of the properties anyway? that would only make sense when you rename the field to match your database column name. But thats a different case, altogether.Caucasoid
I
4

I would not necessary keep only one backing bean per page. It depends on functionality but most of the time I had one bean per page as mostly one page handle one functionality. For example on a page I have a register link (I will link with RegisterBean) and a shopping basket link (ShoopingBasketBean).

I do use this <:outputText value="#{myBean.anObject.anObjectProperty}" /> as I normally keep backing beans as action beans which holds data object. I don't want to write a wrapper in my backing bean to access the properties of my data objects.

Invulnerable answered 14/4, 2009 at 3:21 Comment(0)
C
0

I like to test business code without View's, so I consider BackingBeans as interfaces from View to Model code. I never put any rule or process in a BackingBean. That code goes into Services or Helpers, allowing reuse.

If you use validators, put them out of your BackingBean and reference them from your validation method.

If you access DAOs for filling Selects, Radios, Checkboxes, do that always out of a BackingBean.

Believe me!. You can inject a JavaBean into a BackingBean, but try to inject a BackingBean into another one. You will be soon in a nigntmare of maintenance and understanding code.

Consols answered 13/8, 2013 at 14:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.