wood burning stoves 2.0*
The moose likes JSF and the fly likes Running an application bean method automatically on start? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Java » JSF
Bookmark "Running an application bean method automatically on start?" Watch "Running an application bean method automatically on start?" New topic
Author

Running an application bean method automatically on start?

Jason Irwin
Ranch Hand

Joined: Jun 09, 2009
Posts: 327
I know that application beans are loaded up when they are first needed. I want to accomplish two things.
1) Load the application bean as soon as the application starts;
2) Invoke a method on it to read in some common data

I think I can do 1) like this:
It's 2) that's confusing me. I can't figure out how to run a method once the initialisation is complete (i.e. after the values from faces-config.xml have been loaded). If I put the method call into the constructor, it will run too early. I have thought of using a listener, but how to I get a reference to the Faces Application Bean with just a servlet context and make sure the method is only called after initialisation is complete?

From my searches this is a very common question, but I have no yet found the answer. I'll keep digging and if I find the answer, I'll post it here.


SCJP6
Kenneth Miller
Greenhorn

Joined: Jun 30, 2009
Posts: 7
Assuming your managed bean is session scoped. Why not get it from the session object or construct the managed bean and set it on the session object from a startup servlet.
Eg.
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
MyBean myBean = new MyBean();
myBean.method();
session.setAttribte("myBean", myBean);

I think this should work.

BTW.
the servlet-class in your code clipping should be a servlet. It can't be a managed bean.

HTH.
Regards,
Kenneth
Jason Irwin
Ranch Hand

Joined: Jun 09, 2009
Posts: 327
Thanks Kenneth. My bean is actually application scoped (sorry, I did not make that clear enough) and I need the method to run when the application starts but after Faces has finished the initialisation (i.e. loaded the values from face-config.xml into the bean). That way the first user to request data from the application-scope bean will not have a long wait.

I guess I need something to forces Faces to instantiate the bean and then to invoke the method I want.

I've tried a ServletContextListener, but of course that doesn't work as there is no FacesContext when the application starts up.

I am at a total loss as to how to do this, if it is even possible.
Kenneth Miller
Greenhorn

Joined: Jun 30, 2009
Posts: 7
Hi Jason,
Maybe calling the method from a dummy managed property's setter method might help. Not sure whether the managed property's on a bean are set sequentially based on the order in the faces-config file. Might be worth a try.
Regards,
Kenneth
Jason Irwin
Ranch Hand

Joined: Jun 09, 2009
Posts: 327
I was thinking that might work, but aren't beans lazily initialised? So that'd mean the first user would still get the delay.

What I have done at the moment is placed a check on the login page that will either load the data or show a warning that the system couldn't initialise. Not great, but it works.

I think what I'll have to do at some point is move the config stuff out of faces-config.xml into my own file and then load the bean from there using a listener.
Kenneth Miller
Greenhorn

Joined: Jun 30, 2009
Posts: 7
In startup servlet's init method get hold of the ServletContext, instantiate your managed bean, call it's method and set the managed bean as attribute of the ServletContext.
That seems to do the trick.
Eg.
public void init(ServletConfig config) throws ServletException {
ServletContext context = config.getServletContext();
MyBean myBean = new MyBean();
myBean.setTest("test");
context.setAttribute("myBean", myBean);
super.init(config);
}
When now referencing the managed bean from a jsf page. The test attribute is populated correctly.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16305
    
  21

Jason Irwin wrote:

I've tried a ServletContextListener, but of course that doesn't work as there is no FacesContext when the application starts up.


There's no FacesContext any other time either, except while a JSF Request is being processed.

FacesContext is created on a per-request basis and destroyed (or at least released for garbage collection) as soon as the request response has been sent.

However, there's no difference between creating an application-scope bean manually and having JSF do it other than that the faces-config may inject initialization (post-construction) parameters that would have to be done in Java code otherwise. Once the bean has been constructed, JSF references to the bean won't have any way of knowing whether the bean was constructed via explicit Java code or by the JSF bean manager. Specifically, if the bean is injected into another bean as part of lazy initialization of a managed bean, that should work, and likewise any page reference should work.

Kenneth's example is valid. About the only caveat is that - like all application-scope objects, you should pay attention to possible multi-threading issues and synchronize and accesses to the bean that might corrupt the state of the bean, Which is true also in the case of JSF-only shared beans, since they're POJOs, not EJBs.


Customer surveys are for companies who didn't pay proper attention to begin with.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Running an application bean method automatically on start?