• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

JSF Request Processing Lifecycle Basics

 
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One of the biggest problems I've faced in moving from Struts to JSF is dealing with the JSF lifecycle. In short, stuff happens to the data in my backing beans and I'm spending too much time trying to get the right data on a page and keep it there, unmolested, throughout the JSF request processing lifecycle.

Here is a simple generic use case on which I'd appreciate some basic JSF advice:

Master-to-Detail Navigation: User clicks on a link on page A. The link passes an id value as a request parm to page B where a query for the details are retrieved and displayed.

Page A uses an HtmlOutputLink component with an enclosed UIParameter control to pass a uniqueId as a request parm to the next page.

The questions I have are for page B's managed bean declared to be in request scope:

1) Where should I get request parm value, and store it, so that it stays available throughout all lifecycle operations on the page?

I've pulled it from the request attributes in the constructor and stored it as a field on the bean, but it seems to get nulled out during a later request processing phase.

2) What do I need to do keep safe the detailed record I get using the unique key passed in as a request parm.

If a validation error is found, the data is still there. However, if I navigate back to that same page (i.e. edit -> invoke save action -> return to page for more edits), that's a new request, so the field reverts to null.

Since JSF posts back to the same page, how do I propagate the uniqueId to the next request (which will be for the same page)?

I know I can keep the bean as a session bean, but I'd like to avoid keeping everything in session just to facilitate what should be (probably is) simple navigation in JSF.

Thanks for any advice.

[ February 15, 2006: Message edited by: madjack ]
[ February 15, 2006: Message edited by: madjack ]
 
Ranch Hand
Posts: 362
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Is the link on page A part of a dataTable or something like that linking to a list/array element?
 
Jack J. Jackson
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have two scenarios where this is used. First, Page A has outputLinks not in a dataTable. The second scenario is, the link is in a row in a dataTable.

Should they be handled differently?
 
Gerardo Tasistro
Ranch Hand
Posts: 362
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes. Usually in the non-dataTable case I have a session scope managed bean that holds the data and navigation methods (from the nav rules). So all that changes is the view (jsp) from one page to the other.

In the dataTable case I use a dataModel. I have a linkedList or array with data and that is linked to the dataModel through the setWrappedData. The dataModel is pased to the JSF for html rendering. The links then all call a method (say "showDetails") which uses the getRowData method from the dataTable to set the current clicked on data to a variable called currendRow or something like that. currentRow is then used for JSF rendering in the second page.

I usually use one session bean that knows the state of the application so I don't need to pass state variables between JSPs.
 
Saloon Keeper
Posts: 27752
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Welcome to JavaRanch!

We're not a real uptight bunch here, but we do like to appear professional, so we have a naming policy that requires that JavaRanch display names consist of a real (sounding) first and last name separated by a space.

You can find details here. Please take a moment to read up and then change your display name accordingly.

Aside from everything else, "real" names generally get better answers since some ranchers just ignore questions that when they're asked by someone with an obviously bogus name.
 
Jack J. Jackson
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

... but we do like to appear professional ...



I guess the one-eyed moosehead graphic threw me off on this...

I'll conform before my next post.
 
Jack J. Jackson
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks a lot for the response Gerardo.

For the non-DataTable case, do you recommend a single backing bean for each JSP page like Shale's 1:1 requirement? Or, do you have a single "Controller" bean that keeps data to support multiple views?

Also, how do you trigger the loading of the data after the initial load?

The first reference to the sessionScope backing bean in a JSF component could cause a load of the data, but won't the request processing lifecycle cause that method to be invoked multiple times before the page is ever displayed?

Jack
[ February 16, 2006: Message edited by: Jack J. Jackson ]
 
Gerardo Tasistro
Ranch Hand
Posts: 362
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I use a single controller approach. It keeps the state of the application and all the data (although not directly).

The controller contains the classes that do all the heavy weight data lifting. The controller just exposes their data internals and its own control methods to the JSF.

When you click on a button or command link the action method for the controller gets called. This method talks to the data class which actually gets the beans from the database (in my case through Hibernate).

So for example lets suppose you have a page you want to use to show four types of reports. I set up a selectOneMenu and a button. The action is a method in the controller. It reads the select value and acts accordingly. Do we want to show the latest person who logged it. I call the ShowLatesUser class. Init it and call findLatestUser from the controller. This queries the database and gets a User bean. I create the JSF (either through subviews or forward to proper JSP and access the data by for example:

<h:inputText value="#{controller.manageLatestUser.latestUser.name}" />

I can put a little button that refreshes

<h:commandButton action="#{controller.refreshLatestUser}" />


The method>


public String refreshLatestUser() {

manageLatestUser.refreshUser();
return "refreshed";
}

In this way all the important stuff is kept in the classes and the beans. I can easily move from JSF to say Swing by changing the controller without mods to the other classes or data beans.

Hope this helps.
[ February 16, 2006: Message edited by: Gerardo Tasistro ]
 
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Do you use one controller bean for the whole application? When we were faced with the same question we went for one controller per use-case. And so far we are happy with it.

But I think basically a controller (be it one-for-all or one-per-usecase) seems to be a working approach.

What I like most is, that the controller may be polluted by Framework-calls, whereas the real data-carrying modelbeans can be kept clean.

Alexander
 
Gerardo Tasistro
Ranch Hand
Posts: 362
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Alexander Jesse:
Do you use one controller bean for the whole application? When we were faced with the same question we went for one controller per use-case.




Yes I'm with you on this one. I think we need to define application. For me application is a piece of software that is part of a project which is part of a system. So if the administrator goes into a directory and logs in then thats his little backoffice application. In that case yes it is limited to one controller per use case.

In php I do use a one bean per view approach. But JSP and JSF are so sophisticated I find no real reason to do that. Plus the controller + dataReport objects + data beans give you better feeling that you're running an average desktop application than an snap-shot-a-view web app.
 
Tim Holloway
Saloon Keeper
Posts: 27752
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by madjack:


I guess the one-eyed moosehead graphic threw me off on this...

I'll conform before my next post.



Thanks. It's all in being laid-back, but not too laid-back.
 
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In this way all the important stuff is kept in the classes and the beans. I can easily move from JSF to say Swing by changing the controller without mods to the other classes or data beans.

Interesting concept. I've always gone with the 1:1 route myself with a few session scoped beans that are used throughout the app. I wonder though, with your single controller, at what point does that controller class become unmanagable, if it has to deal with every action from every page.

What if you had a form with 20+ fields? Does the controller then have getter/setters for all those fields, along with whatever action methods are required? What if you had 20 forms with 20+ fields? I'm interested in knowing a few more details on how you handle this with a single controller. Maybe I am just not understanding you correctly.
 
Gerardo Tasistro
Ranch Hand
Posts: 362
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes I think we are getting a bit mistaken here.

The fields are not attributes of the controller. They are attributes of the data beans. These data beans are contained in data classes (which do all the dbase interface) and are in turn contained in the controller.

Now suppose I want to search for a user with a certain name and for simplicity I will only fetch the latest user.

The layout is the following.

Controller : class that will be a managed bean and do just that, be the controller

QueryCriteria : class that has 3 fields: name, lastname and birthdate

CurrentUser : class that goes to the dbase and gets the latest user based on the query criteria. It contains a user variable of type User with a getter and setter for it

User : data bean with all the user data: name, lastname, birthdate, gender, address fields, etc.




Now you see I only have four getters and setters. Two for each field (cUser and qCriteria). All the user field getters and setters are in the user inside the cUser.

So in the jsf I use



Hope this clarifies things. The controller has 2 getters and 2 setters plus one method to trigger the query. All other getters and setters are inside their respective classes. This makes it really easy for me to bind these attributes to a Swing component.
 
Gregg Bolinger
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I see. So your controller only needs access to the beans that relate to each form. So do you use class injections with the managed bean facility or do you physically go into the Controller class each time and define a new bean when there is a new form to deal with? For Example, your CurrentUser class.

The only thing I would do differently, and this might just be a naming convention, is I would use a Service interface that would call the DAO. So rather than CurrentUser, I might have LoginService or UserService and it's implementation call the DAO that fetches the user data.

Thanks for the clarification.
 
Gerardo Tasistro
Ranch Hand
Posts: 362
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Usually when there is a new form there really isn't new data. In my case the form is probably a recook of other views. At best a field gets added, but that is to the data bean. So I don't actually have to modify the controller class in any way other than adding the state-control variables and action methods.

My authentication is container based and I use Hibernate. So DAO isn't really in my TODO list.
 
Gregg Bolinger
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Gerardo Tasistro:
My authentication is container based and I use Hibernate. So DAO isn't really in my TODO list.



Well, technically, your CurrentUser class is a DAO. But I digress...
 
Jack J. Jackson
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Gerardo, Gregg et al:

Thanks so much for the informative discussion!

I was headed down the bean-per-view approach and this was complicating the state management quite a bit. For instance, View A set state in Bean A, but View B needed to use the state set in Bean A. So I was passing state info from managed bean A to managed bean B, but then I couldn't reliably predict when View A would get the updated state, especially if bean B was request scoped.

I just felt this was all getting a little too complicated for what was a really straight-forward web application.

A sessionScoped controller-per-usecase scenario seems much more reasonable. Then, every bean sees the same state at the same time without passing state around from bean to bean.

Thanks again!

[ February 18, 2006: Message edited by: Jack J. Jackson ]
[ February 18, 2006: Message edited by: Jack J. Jackson ]
 
Gerardo Tasistro
Ranch Hand
Posts: 362
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jack a case I would use a bean per view is when nested datatables are used.

For example I have a list that contains items that contain lists that contain items. I want to show a table of the list with nested tables of the sub lists, one per row.

For example a car rental, its centers and the car models per center. I have a list of centers and within them a list of cars models. The way JSF works I use a ListDataModel to show the lists in a <h ataTable>. Problem is I have to relate each center's car model list to a ListDataModel. That makes me use ListDataModel inside the center's bean. Something I don't want to do in real MVC.

A solution would be to use a class that does have all the required DataModels. This class gets the centers list and does all the work to expose its internals without acutally having any JSF stuff inside the data beans.
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic