aspose file tools*
The moose likes JSF and the fly likes how to initialize a backing bean before a page loads Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » JSF
Bookmark "how to initialize a backing bean before a page loads" Watch "how to initialize a backing bean before a page loads" New topic
Author

how to initialize a backing bean before a page loads

Cameron Wallace McKenzie
author and cow tipper
Saloon Keeper

Joined: Aug 26, 2006
Posts: 4968
    
    1

I was searching the JavaRanch forums and found a person running into a similar scenario as me. There were no responses, but I was hoping that perhaps we might get more insight two years later.

Similarly, I have a bean that generates a picklist, which is read from a database. I want to initialize the beans properties before the page loads, and was wondering the best way to do it. I don't want to do it in the constructor, as the constructor seems to get hammered 3 or 4 times as the page gets loaded, and I don't want that many database calls. What's the best practice?

Any response to the thread below is equally valid.

Thanks,

-Cameron McKenzie


Original JavaRanch Thread on Initializing a Backing Bean - Multiple Constructor Calls



Hi,
I have a JSF page and a corresponding backing bean class. To initialize the html form fields within the JSF page, I wrote a piece of code to call a sateful session and get the information from the DB. However, while loading the page, backing bean constructor is getting called twice and hence session bean method is also getting called twice.

1) How can we avoid calling the session bean method more than once?
2) Is there any annotation that can be specified for a method, so that it can be called only once while loading the page?
3) I have seen somewhere saying that prerender can be used to make sure that the corresponding method gets called only once. How to specify that? Any example?

Thanks
-raju
Mohan Ramamoorthy
Greenhorn

Joined: Jan 31, 2006
Posts: 9
Hi Cameron,
I had the same problem earlier and I tried a lot to find out the solution. All went into vein. I did some workaround for this problem. I am not sure that this is the proper solution. But I am sure that it will be helpful to you.

It has few steps to follow
1. Identify each page by some constant value.(ref steps 2.b and 2.d)
2. Implement a class with PhaseListener.
a) depends on the requirement you can use afterPhase/beforePhase method.
b) retrive the page-reference constant from session.
c) use switch case,to find out the appropriate backbean and method
For eg. (mybackbean is your BackBean and init is your your method)

FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
MethodBinding methodBinding = application.createMethodBinding(
"#{mybackbean.init}", null);
if (methodBinding != null) {
try {
methodBinding.invoke(context, null);
} catch (Throwable e) {
}

This code calls the corrosponding method.
d) save the new page-reference in the session

3. Configure the phaselistener in faces-config.xml


The init method shown in the code piece executes the business logic for you..

let me know, if you have any problem with this solution.
Cameron Wallace McKenzie
author and cow tipper
Saloon Keeper

Joined: Aug 26, 2006
Posts: 4968
    
    1

Indeed...I was looking at the phase listener.

I guess you could achieve something similar with a ServletListener configured on the FacesServlet.

Looks like we're not the only ones hitting this conundrum. Seems JSF 1.2 has a solution, developed by people better looking than you and me.

Use JSF 1.2. You can annotation methods within your bean with the @PostConstruct or @PreDestroy annotations. In the case of @PostConstruct,
the method will be invoked on the bean *before* it is put into scope.


Post on Best Practices for JSF Backing Beans / Managed Beans

Unfortunately, I'm deploying to Rational Application Developer, and IBM has a policy of not supporting new standards until they are extremely old.

-Cameron McKenzie
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16062
    
  21

Something's wrong here. A constructor - by definition - can only be invoked once, and it is invoked by the classloader as part of the process of instantiating the bean. So there's no way in any Java framework for the constructor itself to be invoked multiple times on the same bean. Once per instance is all you're allowed.

Loading from a database in a constructor would be a problem anyway, since managed bean constructors can take no arguments, and therefore you couldn't pass in parameters to obtain the database connection - you could only do the work by ugly brute force.

Probably what you really want is to determine if you're using a backing bean in the right scope. For example, if you're developing drop-down lists of constants, these would normally be at application scope, since they'd generally be loaded when the app first started and not modified thereafter, so that way only one trip to the database would be required.

You can define a managed bean to provide your database services and inject it into a page-scope bean if that helps.


Customer surveys are for companies who didn't pay proper attention to begin with.
Cameron Wallace McKenzie
author and cow tipper
Saloon Keeper

Joined: Aug 26, 2006
Posts: 4968
    
    1

A constructor - by definition - can only be invoked once


Indeed. Just seemed that the framework was creating a bunch of instances of the bean, over and over again, needlessly, as opposed to hitting an instances constructor multiple times, which is what I incorrectly stated. I'm hoping that was more of a manifestation of being in 'debug mode' though. The constructor calling zealousness has seemed to subsided.

I just had the discussion this morning of APPLICATION_SCOPE, which I personally love, and think is underused and highly underrated. :thumb: Just doesn't quite cut it for this scenario.

It's just a 'select all' type query with no parameters. Philisophically I don't like putting it in the constructor, but that just might be the hammer I'll have to drop.

Thanks for all the insight. Any more is welcome.

-Cameron McKenzie
Ryan Lubke
Ranch Hand

Joined: Jun 20, 2007
Posts: 36
Originally posted by Cameron Wallace McKenzie:
Indeed...I was looking at the phase listener.

I guess you could achieve something similar with a ServletListener configured on the FacesServlet.

Looks like we're not the only ones hitting this conundrum. Seems JSF 1.2 has a solution, developed by people better looking than you and me.



Post on Best Practices for JSF Backing Beans / Managed Beans

Unfortunately, I'm deploying to Rational Application Developer, and IBM has a policy of not supporting new standards until they are extremely old.

-Cameron McKenzie


If using JSF 1.2, look at the beforePhase and afterPhase attributes provided.

http://java.sun.com/javaee/javaserverfaces/1.2_MR1/docs/tlddocs/f/view.html
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16062
    
  21

That seems a little baroque for most purposes. I'd go with the application scope bean injection, if for no other reason than when the Next Big Framework comes out, there's JSF-specific code to replace. Or, if you prefer an alternative reason: if you don't code JSF into your beans, you don't need to have JSF running to unit-test them.

Application Scope is underappreciated. It's a perfect place to put things that are application-global. They need not be totally invariant, but any changes to application scope objects do have to be considered in the light that they will immediately be changed for all users of the application. Menu droplists are generally OK with this mode of operation.

A typical architecture for me would look like this:

ConnectionBean -I-> DAOBean -I-> ApplicationBean -I-> PageBean

The "-I->"s indicate external injection. For the first two, I let Spring construct and inject. For the last two, I let JSF do the construction and injection.

While this makes for a lot of components, each component is simple and to the point, can be tested in isolation, and is even occasionally reusable. Thus I trade structural complexity for a monolithic specialized solution that has fewer components, but is usually harder to test and maintain, and is almost guaranteed not to be reusable.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16062
    
  21

Originally posted by Bob Good:
Application scope is once for entire app, so if drop down contents change, you have provide a means to refresh the cached ones.

[ March 07, 2008: Message edited by: Bob Good ]


That is correct. Fortunately that's just a matter of providing an action method in the application scope bean to do the updating. For adding additional dropdown menu constants, this is fairly safe and simple. If you're deleting items or doing other things that can break some other user's workflow, of course you have to take normal multi-threading precautions.

There are unquestionably times when an action needs to be done once on a user session's first page load - although thanks the way a user can hop-scotch around a webapp, it isn't always easy to figure out what can be defined as "first page load" - since it might be first-per-session or first-in-workflow, a direct URL jump or some other criteria (and then there's the infamous browser Back Button...).

All I'm really saying is that there's a notable tendency for JSF programmers to adopt complex solutions to simple problems. I'm very grateful that it's possible to create complex solutions in JSF, but I'd prefer to leave them for complex problems.

I suppose it's only natural that many JSF questions have a predefined solution embedded in them - most people have probably come up with a strategy and struggled with it before they get desperate enough to ask for outside help. However, it's always useful to step back and look at what you're trying to get done, lest you get lost in how you're trying to do it. A really rich environment such as JSF, often provides many solutions for a problem, but some tend to be better suited for the particular goal in question.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16062
    
  21

Whoa, now! Don't go away mad. You've pulled a contribution that someone may find valuable someday - possibly me!

There was no personal attack implied here. I was merely observing that JSF is an immensely powerful framework. So powerful, in fact, that I've learned that whenever I am tempted to construct a complicated solution to a problem, it's worth checking to see if they haven't already solved that problem in a simpler way. It's an observation I've made many times before in this forum and it's not a reflection on anyone's intelligence or competencies - JSF is like that.

I'm a firm believer in Einstein's comment that "Everything should be as simple as possible but no simpler. Some problems have simple solutions, some don't.

Cameron's question originally stated was how to make a dropdown menu from a database table while keeping the overhead to a minimum. Unstated was how volatile that menu was, whether it was context-sensitive or not, whether other users would be affected, and other things. My suggestion was based on a common scenario in which menus were essentially static for the life of the application. It's a solution that I've used not only with JSF, but with Struts, but JSF makes it simpler, since the JSF framework will construct the objects automatically. The overhead is about as low as you can get, since the application object is constructed and populated once per application execution. However, as a solution it's not suitable if the required menu varies with the user's workflow.

There's a time for simple and there's a time for complex. I recommend simple when you can get away with it, if for no other reason that it allows more leisure to get the complex stuff right.
remove ps
Greenhorn

Joined: Mar 17, 2008
Posts: 2
Originally posted by Cameron Wallace McKenzie:

Post on Best Practices for JSF Backing Beans / Managed Beans



The @PostConstruct annotation is quite nice, but the docs at <http://java.sun.com/javaee/5/docs/api/javax/annotation/PostConstruct.html> say that the method must not throw any checked exceptions (which are exceptions other than RuntimeException). But what if reading from the database throws, say a SQLException? In this case, I'd like the bean to not be constructed, and to show the error on the page.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: how to initialize a backing bean before a page loads