How to call Managed bean method in using expression language - jsf-2

I am developing a utility class, using this we need to call a managed bean method which is defined in EL Expression. Is there any examples like how to invoke a managed bean method using EL expression.
Here I don't know the type of Managed bean. but I know EL expression. So I cannot type cast to specific managed bean.
The expression is: #{phaseListenerBean.compListener}
How can my code call the compListener method on phaseListenerBean?
My Utility class. It is avaliable in a Jar file.
`public void beforePhase(PhaseEvent event) {
if(PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())){
SystemListLoaderHelper.populateSelectOneValidValues();
SystemListLoaderHelper.populateSelectManyCheckboxValidValues();
FacesContext context = FacesContext.getCurrentInstance();
ExpressionFactory factory =context.getApplication().getExpressionFactory();
MethodExpression methodExpression = factory.createMethodExpression(
context.getELContext(), "#{phaseListenerBean.callModuleSpecificServiceCalls}",
Void.class.getClass(), null);
methodExpression.invoke(context.getELContext(), null);
// callModuleSpecificServiceCalls();
}
}`

You can try call the bean with the Faces context, for example if you want the bean, you can use:
FacesContext facesContext = FacesContext.getCurrentInstance();
Object o = facesContext.getApplication().evaluateExpressionGet(facesContext,
"#{phaseListenerBean}", Object.class);
And later use reflection to call the method or, You can call the method whith your expression, like this:
FacesContext fc = getContext();
ExpressionFactory factory = getExpressionFactory();
methodExpression = factory.createMethodExpression(
fc.getELContext(), "#{phaseListenerBean.compListener}",
Void.class, (Class<?>) null);
methodExpression.invoke(fc.getELContext(), null);
Please show some code for "compListener" and the utility class. Sorry for my bad english,
Cheers

Related

Expression Language Other way to invoke method

I have the following code and I'm searching for an other way to do this.
public static RequestContextData getRequestContextData() {
FacesContext fc = FacesContext.getCurrentInstance();
ExpressionFactory ef = fc.getApplication().getExpressionFactory();
MethodExpression me = ef.createMethodExpression( fc.getELContext(), "#{requestContextData.getRequestContextData}", String.class, new Class[0]);
Object o = me.invoke(fc.getELContext(), null);
RequestContextData request = (RequestContextData) o;
return request;
}
I found out that it causes problems after upgrading to tomcat 8. The ELContext is already resolved and with this code afterwards it wouldn't be resolved anymore. I already tried it with a managed property but this won't work.
Addition 1:
The stack looks like the following:
xxx.getRequestContextData()
some other methods
BeanELResolver.getValue(ELContext, Object, Object)
The ELContext is in BeanELResolver and xxx the same one. That leads to the malfunction that the xxx overwrites the resolved property with false in the BeanELResolver which then returns an PropertyNotFoundException.

How do I know which EL expression is triggering particular bean method?

There is a bean method which provides data for a number of xthml tags on a page. For debugging purposes I'd like to know which node in a ViewRoot is triggering the method. Something like that:
<ui:repeat id="alpha" value="#{myBean.objectList}" var="obj">
<!-- some stuff here -->
</ui:repeat>
and the method itself:
public List getObjectList() {
String id = ????;
logger.info("I'm being called by:" + id); // returning "alpha", "beta"
// or whatever component
// calling this method
}
Is it possible?
You can use UIComponent#getCurrentComponent() to obtain the UI component instance currently being processed in the JSF lifecycle.
UIComponent currentComponent = UIComponent.getCurrentComponent(FacesContext.getCurrentInstance());
String currentComponentId = currentComponent.getId();
// ...

Get only in-service CDI managed beans

My goal is to get a collection of all in-service CDI managed beans (of a certain parent class) from within a JSF2 ExceptionHandlerWrapper. Note the exception handler part is significant because the class is not a valid injection target itself. So my assumption (maybe incorrect) is that my only route is programmatic through BeanManager.
Using BeanManager.getBeans, I can successfully get the set of all beans available for injection. My issue is that when using BeanManager.getReference to obtain the contextual instance of the bean, the bean will be created if it does not already exist. So I am looking for an alternative that will only return instantiated beans. The code below is my starting point
public List<Object> getAllWeldBeans() throws NamingException {
//Get the Weld BeanManager
InitialContext initialContext = new InitialContext();
BeanManager bm = (BeanManager) initialContext.lookup("java:comp/BeanManager");
//List all CDI Managed Beans and their EL-accessible name
Set<Bean<?>> beans = bm.getBeans(AbstractBean.class, new AnnotationLiteral<Any>() {});
List<Object> beanInstances = new ArrayList<Object>();
for (Bean bean : beans) {
CreationalContext cc = bm.createCreationalContext(bean);
//Instantiates bean if not already in-service (undesirable)
Object beanInstance = bm.getReference(bean, bean.getBeanClass(), cc);
beanInstances.add(beanInstance);
}
return beanInstances;
}
Here we are...poking through the javadoc I found Context which has two versions of a get() method for bean instances. One of them, when passing in a creational context, has the same behavior as BeanManager.getReference(). However the other just takes a Bean reference and returns either the contextual instance (if available) or else null.
Leveraging that, here is the version of the original method which returns only instantiated beans:
public List<Object> getAllCDIBeans() throws NamingException {
//Get the BeanManager via JNDI
InitialContext initialContext = new InitialContext();
BeanManager bm = (BeanManager) initialContext.lookup("java:comp/BeanManager");
//Get all CDI Managed Bean types
Set<Bean<?>> beans = bm.getBeans(Object.class, new AnnotationLiteral<Any>() {});
List<Object> beanInstances = new ArrayList<Object>();
for (Bean bean : beans) {
CreationalContext cc = bm.createCreationalContext(bean);
//Get a reference to the Context for the scope of the Bean
Context beanScopeContext = bm.getContext(bean.getScope());
//Get a reference to the instantiated bean, or null if none exists
Object beanInstance = beanScopeContext.get(bean);
if(beanInstance != null){
beanInstances.add(beanInstance);
}
}
return beanInstances;
}

How to create action for HtmlCommandLink#setActionExpression()

I am trying to add commandlink programatically, but I am not able to add action.
HtmlCommandLink link = new HtmlCommandLink();
link.setValue(data);
link.setActionExpression(no idea);
How do I create it?
Use ExpressionFactory#createMethodExpression().
Here's a convenience method:
private static MethodExpression createMethodExpression(String expression, Class<?> returnType) {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().getExpressionFactory().createMethodExpression(
context.getELContext(), expression, returnType, new Class[0]);
}
Here's how you could use it, provided that you've a public String doSomething() {} action in a managed bean identified by #{bean}:
link.setActionExpression(createMethodExpression("#{bean.doSomething}", String.class));

Setting bean property from validator

Is there a way to set a bean property from a Validator?
In my case, I have a validator which connects to the database and performs some validation.
Upon successful validation, I want to save the object received from database, inside a bean property.
Currently i'm doing this by setting a static property of my bean from the validator.
Here is my validator method
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
//perform validation
if(isValidated) {
Referral ref = database.getReferral(value.toString()); //receive referral object from batabase
RegistrationBean.staticReferral = ref; // Set ref to RegistrationBean's static property
} else {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_FATAL, "Invalid Referral!", "Referral does not exist!");
throw new ValidatorException(msg);
}
}
and here is my RegistrationBean
#ManagedBean
#ViewScoped
public class RegistrationBean implements Serializable {
//other bean properties
private Referral referral;
public static Referral staticReferral;
public RegistrationBean() {
//default constructor
}
public Referral getReferral() {
this.staticReferral = referral;
return referral;
}
// other getters, setters and methods
}
So the questions in my mind are:
Is there a way to set a bean property directly from a bean? (without
using a static property)
Would there be any concurrency issues (one user may receive other user's selected referral object etc) using the existing approach?
Thanks
Static members in managed beans are shared among all instances (and users of your application). So think at least twice before making a member variable static.
If you make your validator a managed bean, you can inject your target managed bean into your validator. See this answer for details.
In the given example an EJB is injected, but you can inject a JSF managed bean via the #ManagedProperty annotation

Resources