Making Managed Beans Aware of the JSF Lifecycle
June 6, 2006 12 Comments
An event that runs when a JSF page is being loaded should be useful for initialization stuff. In my project team several developers use bean constructors to do such things which I think is a bad practice. Although I prefer the getters to do initializations, I’ve added a onPageLoad event to our application for people who prefer the constructors. It is similiar to Shale view mapper, the managed bean and the page name must be mapped in order to run the event. There are two things needed to do the job, a phaselistener and an interface to mark the managed beans. PhaseListener runs maps the viewId to the managed bean and executes the onPageLoad event.
|
And the interface that makes the managed bean aware of the lifecycle.
|
For example there is a page called index.jsp, and it is referred as the virtual mapping /index.jsf. Phaselistener extracts the index token and gives the mapping pc_Index. Also the managed bean class Index.java implements ILifeCycleAware interface and overrides the onPageLoad event. Then phaselistener executes this event. Finally the backing bean of index.jsp is declared in faces-config.xml as;
<managed-bean> <managed-bean-name>pc_Index</managed-bean-name> <managed-bean-class>barca.Index</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> |
The good thing is more events can be added like the ones in Shale, eg prerender, preprocess and etc. So you can execute similiar events and make the managed beans aware of the lifecycle.
Usage of “pc_” prefix for backing bean names is a good practice from IBM. All hail IBM.
Any reason for not using this guy?
http://jsf-comp.sourceforge.net/components/onload/index.html
A good alternative for onLoad, but doesn’t seem to be extendable. What if I need more events like prerender etc.
Will this work if a bean is lost because of a session timing out?
I guess so since JSF will create a new instance when it is referred for the first time.
Hi!
I’m trying out this technique to do some init work in my managed bean. but phaseEvent.getFacesContext().getViewRoot() returns null. Any idea why this would happen?
Rgds,
Deepak
Hi Cagatay
I have used the above technique to retrieve incoming Http Request Header Variables . As suggested i have onPageLoad event defined in MyPhaseListener & Backing Bean. But the header variables are returning NULL values. Am i missing anything here.
Here are snippets of code
————–
————–
————–
com.mycompany.MyPhaseListener
faces-config.xml
————–
com.mycompany.TestJsfBean
Can i have two references to TestJsfBean with different names as shown above. Hope this is not the mistake i am making
————–
MyPhaseListener.java
————–
public void afterPhase(PhaseEvent pe)
{
System.out.println(“after – ” + pe.getPhaseId().toString());
FacesContext facesContext = pe.getFacesContext();
String viewId = pe.getFacesContext().getViewRoot().getViewId();
System.out.println(“ViewId =”+viewId);
if (viewId.endsWith(“.jsp”)) {
String managedBeanName = getManagedBeanNameFromView(viewId);
Object object = facesContext.getApplication().createValueBinding(“#{” + managedBeanName + “}”).getValue(facesContext);
if (object == null)
logger.error(“OnPageLoad cannot be executed, no such managed bean:”+ managedBeanName);
else {
ILifeCycleAware lifeCycleAwareBean = (ILifeCycleAware) object;
lifeCycleAwareBean.onPageLoad();
}
}
————–
TestJsfBean.java
————–
public void onPageLoad() {
Map requestHeaderMap = new HashMap();
requestHeaderMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
System.out.println(“Hash Map Size in TestJsfBean:”+requestHeaderMap.size());
String bemsId = (String)requestHeaderMap.get(“BOEINGBEMSID”);
System.out.println(“In TestJsfBean:”+bemsId);
//return bemsId;
}
————–
ILifeCycleAware
————–
package com.mycompany;
public interface ILifeCycleAware {
public void onPageLoad();
}
I dont have problem with accessing requestParameterMap in PhaseListener (RESTORE_VIEW). But please note i am not able to access it in the Backing Bean method i.e. onPageLoad()
The reason i am doing this is i would like to store my Http Request Header variables in Backing Bean method based on which i will perform some business logic & then accordingly i will render my first jsp page of the application
The Phase Id is RENDER_RESPONSE in afterPhase() method from where the onPageLoad() method is called i.e
lifeCycleAwareBean.onPageLoad();
Please let me know if i am missing something or taking a wrong path. I would appreciate your quick response. Also can i have different bean names refering to same bean class in faces-config.xml i.e.
com.mycompany.TestJsfBean
Pl note pc_GreetingList and testJsfBean are two different bean names refering to same bean class com.mycompany.TestJsf Bean
I have tried this method out as well.. it appears the view root is always returning the previous page’s view root /page1 -> page2 -> page3
when going to page 3 i get page2 in the view root.
the solution is without adding to your navigation rule, this will not work.
Hi, I actually would like to know how you maintain this wonderfully formatted source code within a wordpress page. Seems at least that you are pasting from an eclipse editor.
What wordpress plugin are you using. I have tried several with only disappointing results!
Thanks
Martin
Hi Martin, Check this out: http://www.java2html.de/