Enterprise Java

5 useful methods JSF developers should know

The aim of this post is a summary about some handy methods for JSF developers they can use in their day-to-day work. An utility class is a good place to put all methods together. I would call such class FacesAccessor. The first method is probably the most used one. It returns managed bean by the given name.

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.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
abani behera
abani behera
12 years ago

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}

Oleg Varaksin
Oleg Varaksin
12 years ago

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”.

Cooljnr
Cooljnr
11 years ago
Reply to  Oleg Varaksin

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

Jorge Pacheco
Jorge Pacheco
12 years ago

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

Rafael
Rafael
10 years ago

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!

Peter Tutoring
9 years ago

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

cristhianguedes
cristhianguedes
9 years ago

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…

Samruddhi Misal
Samruddhi Misal
8 years ago

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 »

Raghu
Raghu
7 years ago

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) ?

Back to top button