5 useful methods JSF developers should know
The bean must be registered either per faces-config.xml or annotation. Injection is good, but sometimes if beans are rare called, it’s not necessary to inject beans into each other.
public static Object getManagedBean(final String beanName) { FacesContext fc = FacesContext.getCurrentInstance(); Object bean; try { ELContext elContext = fc.getELContext(); bean = elContext.getELResolver().getValue(elContext, null, beanName); } catch (RuntimeException e) { throw new FacesException(e.getMessage(), e); } if (bean == null) { throw new FacesException("Managed bean with name '" + beanName + "' was not found. Check your faces-config.xml or @ManagedBean annotation."); } return bean; }
Using:
@ManagedBean public class PersonBean { ... } PersonBean personBean = (PersonBean)FacesAccessor.getManagedBean("personBean"); // do something with personBean
The second method is useful for JSF component developers and everyone who would like to evaluate the given value expression #{…} and sets the result to the given value.
public static void setValue2ValueExpression(final Object value, final String expression) { FacesContext facesContext = FacesContext.getCurrentInstance(); ELContext elContext = facesContext.getELContext(); ValueExpression targetExpression = facesContext.getApplication().getExpressionFactory().createValueExpression(elContext, expression, Object.class); targetExpression.setValue(elContext, value); }
Using:
I personally use this method for the “log off functionality”. After an user is logged off, he/she will see a special “logoff page”. The “logoff page” uses user settings (e.g. theme, language, etc.) from a sesion scoped bean. But this session scoped bean doesn’t exist more because the session was invalidated. What to do? Here is the code snippet from my logout method.
UserSettings userSettings = (UserSettings) FacesAccessor.getManagedBean("userSettings"); // invalidate session ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); HttpSession session = (HttpSession) ec.getSession(false); session.invalidate(); // create new session ((HttpServletRequest) ec.getRequest()).getSession(true); // restore last used user settings because login / logout pages reference "userSettings" FacesAccessor.setValue2ValueExpression(userSettings, "#{userSettings}"); // redirect to the specified logout page ec.redirect(ec.getRequestContextPath() + "/views/logout.jsf");
The third method maps a variable to the given value expression #{…}. It uses javax.el.VariableMapper to assign the expression to the specified variable, so that any reference to that variable will be replaced by the expression in EL evaluations.
public static void mapVariable2ValueExpression(final String variable, final String expression) { FacesContext facesContext = FacesContext.getCurrentInstance(); ELContext elContext = facesContext.getELContext(); ValueExpression targetExpression = facesContext.getApplication().getExpressionFactory().createValueExpression(elContext, expression, Object.class); elContext.getVariableMapper().setVariable(variable, targetExpression); }
Using:
Assume, “PersonBean” is a managed bean having “name” attribute and “PersonsBean” is a bean holding many instances of “PersonBean” (as array, collection or map). The following code allows to use “personBean” as a reference to a specific bean with “name” Oleg.
FacesAccessor.mapVariable2ValueExpression("personBean", "#{personsBean.person['Oleg']}");
In a facelets page, say so, personDetail.xhtml, we can write:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <ui:composition> ... <h:inputText value="#{personBean.name}"/> ... </ui:composition> </html>
Note, the reference “personBean” was set in Java. This mapping can be also used in facelets in declarative way via ui:include / ui:param.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <ui:composition> ... <ui:include src="personDetail.xhtml"> <ui:param name="personBean" value="#{personsBean.person['Oleg']}"/> </ui:include> ... </ui:composition> </html>
The next two methods are used to create MethodExpression / MethodExpressionActionListener programmatically. They are handy if you use component binding via “binding” attribute or create some model classes in Java.
public static MethodExpression createMethodExpression(String valueExpression, Class<?> expectedReturnType, Class<?>[] expectedParamTypes) { MethodExpression methodExpression = null; try { FacesContext fc = FacesContext.getCurrentInstance(); ExpressionFactory factory = fc.getApplication().getExpressionFactory(); methodExpression = factory. createMethodExpression(fc.getELContext(), valueExpression, expectedReturnType, expectedParamTypes); } catch (Exception e) { throw new FacesException("Method expression '" + valueExpression + "' could not be created."); } return methodExpression; } public static MethodExpressionActionListener createMethodActionListener(String valueExpression, Class<?> expectedReturnType, Class<?>[] expectedParamTypes) { MethodExpressionActionListener actionListener = null; try { actionListener = new MethodExpressionActionListener(createMethodExpression( valueExpression, expectedReturnType, expectedParamTypes)); } catch (Exception e) { throw new FacesException("Method expression for ActionListener '" + valueExpression + "' could not be created."); } return actionListener; }
Using:
In one of my projects I have created PrimeFaces MenuModel with menu items programmatically.
MenuItem mi = new MenuItem(); mi.setAjax(true); mi.setValue(...); mi.setProcess(...); mi.setUpdate(...); mi.setActionExpression(FacesAccessor.createMethodExpression( "#{navigationContext.setBreadcrumbSelection}", String.class, new Class[] {})); UIParameter param = new UIParameter(); param.setId(...); param.setName(...); param.setValue(...); mi.getChildren().add(param);
Do you have nice methods you want to share here? Tips / tricks are welcome.
Reference: 5 useful methods JSF developers should know from our JCG partner Oleg Varaksin at the Thoughts on software development blog.
Hi, you have provided nice article. I want to add few comments on the your first section (
getManagedBean method). from your code snippet, it looks you are using JSF2. If so, getting an instance of managed bean is pretty easy. We have one annotation
through which we can get the instance of any object, which is maintained by FacesServlet.
Below I have given a sample code.
@ManagedBean:disqus @SessionScope:disqus
public class PersonBean {}public class AccountBean{ @ManagedProperty:disqus (“#sessionScope.PersonBean”) private PersonBean person; // must have getter/setter for PersonBean}
Hi, I know about ManagedProperty. But it’s an injection and as I said in the article “Injection is good, but sometimes if beans are rare called, it’s not necessary to inject beans into each other”.
Hi,developing online exam test (multiple choices question)with jsf in java ee but do not know to go about it.please l need your help.thank you
Hi, I have a problem with the example ‘create MethodExpression’ with menuModel.
When the menu is inside an accordion, the actionExpresion not working.
Any ideas?
thanks
Oleg these methods are excellent. Especially first one, I agree with you about injection sometimes it’s not necessary to initialize every beans at the same time. Thank for this article!
be aware:
05 HttpSession session = (HttpSession) ec.getSession(false);
06 session.invalidate();
when session doesnt exist – for example timeout – then session is null and come to NullPointerException
I the first method, i think that is better to use generics in the return method:
public static T getManagedBean(final String beanName) {
FacesContext fc = FacesContext.getCurrentInstance();
Object bean;
try {
ELContext elContext = fc.getELContext();
bean = elContext.getELResolver().getValue(elContext, null, beanName);
} catch (RuntimeException e) {
throw new FacesException(e.getMessage(), e);
}
if (bean == null) {
throw new FacesException(“Managed bean with name ‘” + beanName
+ “‘ was not found. Check your faces-config.xml or @ManagedBean annotation.”);
}
return (T) bean;
}
This way, you can use simply:
MyBean mB1 = FacesAccessor.getManagedBean(“myBean”);
or
PersonBean pB1 = FacesAccessor.getManagedBean(“personBean”);
Less of code…
Hi. I have been trying to maintain a single session for user in adf. What I have done is I have created a login page and now what I want is that if the user is already logged in once and tries to login again from another tab or browser then he should be prompted that You are already logged in or Please log out before login. Besides if the user still logs in then the session of previously opened login page should be terminated and the user should be allowed to login. I have posted the query on oracle… Read more »
Hi,
MenuItem mi = new MenuItem();
02
mi.setAjax(true);
03
mi.setValue(…);
04
mi.setProcess(…);
05
mi.setUpdate(…);
06
mi.setActionExpression(FacesAccessor.createMethodExpression(
07
“#{navigationContext.setBreadcrumbSelection}”, String.class, new Class[] {}));
here how to pass a parameter to the action method .setBreadcrumbSelection(url) ?