• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Running an application bean method automatically on start?

 
Jason Irwin
Ranch Hand
Posts: 327
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Kenneth Miller
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 327
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 327
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 18154
52
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic