4

Should I have a bean for every form, datatable etc in JSF?

For example, I have a form for registration, which simply has 2 fields and a button which are: nickname, password, submit

Should submitting this form go to a RegistirationFormBean or somewhere in UserBean or UserServiceBean?

What is the best practice?

Thank you.

Sazzadur Rahaman
  • 6,938
  • 1
  • 30
  • 52
Koray Tugay
  • 22,894
  • 45
  • 188
  • 319

4 Answers4

4

To decide whether or not you should create a @ManagedBean exclusively for a component of the page (e.g. form, datatable), I believe you should think about the modularity of your design.

The 1st question you should ask yourself is: Will the component be re-used in many pages?. For example, on sensitive pages such as ChangePassword or DeleteAccount, usually, you will ask the user to enter the current password to validate his identity before performing any logic. In this case, you should definitely have an exclusive bean for the validating password component so that you can re-use the component again and again without having to re-code the validating function every time.

Secondly, I usually use @ManagedBean as a place to hold all the related functions that work toward the same goal. This grouping of functions can be pretty subjective. For example, I can have a page called CreateProduct.xhtml with a bean called CreateProductBean that has all the functions for creating a product. In this case, it's like 1 bean per view. Another way is to have a bean called ProductManager that has functions for everything related to the Product object (i.e. create, read, update, remove). In this case, it's like 1 bean for many views (e.g. CreateProduct.xhtml, RemoveProduct.xhtml). For ease of future maintenance and division of work, I usually use 1 bean per view. The 2nd approach 1 bean for many views is also good on certain situations but I suddenly cannot think of an example yet :P... I will update my answer when I got a good one ;).

Thirdly, I prefer to follow the 3-tier MVC model and separate back-end logic away from the front-end. For example, to persist a new account in the database, I will inject an @EJB or a @WebServiceRef to ask the back-end system to perform the necessary logic. It's definitely more maintenance friendly in the future :).

So, using your RegisterAccount example, I will have

  • 1 bean called UserExistenceValidator to check if a nickname exists in the database. During registration, I can throw an error if the user chooses a nickname that is taken. I can also use this bean to check if a user exists in the AddFriend.xhtml page.
  • Another bean called RegistirationFormBean to capture a user's inputs and talk to the back-end to persist the new account.
Mr.J4mes
  • 9,168
  • 9
  • 48
  • 90
  • CreateProductBean and ProductManager bean are then both of requestscoped? – Koray Tugay Apr 20 '13 at 07:33
  • @KorayTugay: `@Scope` is another story :P... `CreateProductBean` should definitely be `@RequestScoped`. However, as for `ProductManager`, you may need to have a property called `List` to help display products for updating, removing, etc. In these situations, most of the time, I use `@ViewScoped`. – Mr.J4mes Apr 20 '13 at 10:26
  • All this is explained in the link I've posted as related on OP's question. BalusC even explains the different *kinds* of managed beans and their respective scope... – Luiggi Mendoza Apr 27 '13 at 16:05
  • 1
    @LuiggiMendoza: Sorry, I don't see BalusC's explanation has anything to do with my answer :). Even BalusC's answer is related to the OP's question in some sense, my answer is more to the point of what I myself think is important in deciding the design of an application. – Mr.J4mes Apr 27 '13 at 20:38
2

Its actually a pretty interesting topic to tweak any JSF lover's brain, so I could not resist myself and I would like to go with detail explanation.

One of the very interesting and significant cause behind the invention of JSF was, wiring client side event to server side application code like any swing application and getting rid of handing of request and response object explicitly. Like any swing application, we can now simply bind any client side event (say, button click) with some server side code to handle that event, without worrying the facts and complexities of writing an web application.

As a result when designing any web apps, that uses JSF, the designer can focus on the user experience as easily as designing an event driven swing application. So as the consequence, you design the view pages and identify the events to do tasks and navigate between the views. Finally you write some server side codes to be executed in those events, to do the job you want. Those server side codes reside in your managed beans.

If we classify based on the type responsibility, there are several types of managed beans:

  • Model Managed-Bean
  • Backing Managed-Bean
  • Controller Managed-Bean
  • Support Managed-Bean
  • Utility Managed-Bean

You will find the details of each of the type in this article.

Your problem is, how to distribute the responsibilities of Controller Managed-Bean. There are several issues to consider, while you are distributing this kind of responsibilities:

  1. The complexity of the task to do.
  2. Re-usability of it.
  3. Modularity in terms of responsibility (type of jobs to do).
  4. Modularity in terms of business perspective.
  5. Decoupling the responsibilities. etc.

You can design your system to with a single controller for all the views of your simple CURD operations of a model. But if you need to handle multiple complex transactions in your single create operation, then separating the operations to multiple controllers, would be a better design. Though your registration procedure is pretty much simple, you should use a separate controller to handle the task. Because it will not be a good idea, to put any task in the same managed bean, that is not simple and related enough to reside with the task "registration". I think this, concludes your query!

Sazzadur Rahaman
  • 6,938
  • 1
  • 30
  • 52
0

you should a data transfer object bean and a domain bean for ui submission and for persistence in db respectively. using a controller class, process your ui jsf submission data and create a clean domain bean and use this to persist.

the best practice should always de-couple processes/entities if possible. also your dto bean might have accessory and more data than your domain bean which u might require for several purposes.

Ashish Thukral
  • 1,445
  • 1
  • 16
  • 26
0

In similar situations, I always have a UserManagedBean that handles user relative operations, such as login, registration, change password, etc...
To deal with these operations, I put an attribute in the UserManagedBean of type User (or whatever class name) which corresponds to the persisted data related to users (usually in DB table user).
In your case nickname and password are attributes of the User class. As for the submit it will invoke a method in the UserManagedBean to authenticate user:

<h:inputText value="#{userManagedBean.user.nickname}"/>
<h:inputSecret value="#{userManagedBean.user.password}"/>
<h:commandButton value="Login" action="#{userManagedBean.loginUser}"/>

Of course, the loginUser method will invoke a call to the service layer which will invoke DAO layer to check credentials against DB (or other storage).
If the login is successful, the user attribute in our managed bean (which should be session scoped) is initialized with returned object from DB.

Laabidi Raissi
  • 3,263
  • 1
  • 22
  • 28
  • Do you also have something like if user in UserManagedBean is not null, then the user is logged in? – Koray Tugay Apr 20 '13 at 07:56
  • you mean direct redirection ? if yes, then you should use a filter, in which you can implement both the "remember me" function and the redirection when user is already logged in – Laabidi Raissi Apr 20 '13 at 08:52