MethodExpression invocation without parameters in JSF 2.0 - jsf

I'm trying to invoke a parameterless method from a JSF 2.0 facelet by
#{myBean.foo()}
(without any surrounding tag).
According to Burns/Schalk: The Complete Reference: JSF 2.0 that's possible (page 126, #{userBean.pullValuesFromFlash( )}).
However the framework takes the expression to be a value expression and thus thinks that foo should be a bean property.
On JBOSS 7.0.1 (and 6, too) I get a
"The class '...' does not have the property 'foo'"
error message.

Judging by this response on the JBoss forum, method expressions must only be used in attributes that support them.
Stan Silvert wrote:
It looks to me like this is working as expected. This has nothing to
do with a lack of arguments. Your expression,
#{elManagedBean.hello()} is being treated as a ValueExpression. If
you changed your method to getHello() then it would work. The
question is, should it be treated as a ValueExpression or a
MethodExpression? For instance, if you had the same expression in an
action attribute it would be treated as a MethodExpression.
<h:commandButton value="Hello" action="#{elManagedBean.hello()}"
id="submit_button"/>
You have put the expression in the middle of
the Facelets page and not as the value of an attribute. As far as I
know, this will always be treated as a ValueExpression. I don't see
how this would work in Glassfish. It's possible that there is some
code that tries it out as a ValueExpression and then tries it as a
MethodExpression if it fails. However, I think that would go against
the EL spec. In other words, I'm surprised that this would work on
Glassfish.

McDowell has answered the cause of the problem: inline expressions are treated as value expressions, not as method expressions.
As to how to achieve the functional requirement anyway, use <f:event>.
<f:event type="preRenderView" listener="#{myBean.foo}" />
This will invoke the method right before render response.

This depends on the EL version you are using on your servlet container. If using Tomcat 6, EL 2.1 is included and this does not support '()' as MethodExpression if the expression is in the middle of the Facelets page. Tomcat 7, which includes EL 2.2 does support this and even enhanced features as being able to pass parameters to the method expression:
So you do this:
<h:outputText value="#{object.test(10)}" ></h:outputText>
And receive the parameter in your bean (extra conversion and validation might be needed):
public String test(MyObject o)
{
...
return value;
}
References:
http://tomcat.apache.org/whichversion.html
Using EL 2.2 with Tomcat 6.0.24

Related

Immediate and deffered evaluation EL

Let we have some facelet 1.xhtml that contains
<h:inputText id="prop" value="#{MyBean.myProperty}"/>
and facelet 2.xhtml that contains
<h:inputText id="prop" value="${MyBean.myProperty}"/>
Quote from official tutorial:
Immediate evaluation means that the expression is evaluated and the result returned as soon as the page is first rendered.
I dont understand at what specific phase immediate expression is evaluate? At Render Response phase or Update model values or Apply request or what?
The tutorial is talking about legacy JSP. When using JSF on JSP, the ${} is always evaluated during view build time, regardless of where it's declared. It's like as how JSTL, taghandlers and id/binding attributes work in JSF. See also JSTL in JSF2 Facelets... makes sense? for some in depth explanation.
In JSP's successor Facelets, however, the ${} is treated exactly the same way as #{}. So ${} evaluation is also deferred. To avoid confusion among yourself and the future maintainers of your Facelets code, it's strongly recommended to abandon usage of ${} in Facelets and stick to #{} all the time.
The deferred expression is evaluated every time when its result is needed during runtime. In case of UIInput components, that's one time during validations phase (to check if the submitted value has changed as compared to (old!) model value, before triggering all value change listeners) and one time during render response (to generate HTML output with (new!) model value). If it were evaluated immediately, setting and obtaining the new model value wouldn't have worked.
See also:
Difference between JSP EL, JSF EL and Unified EL
Why JSF calls getters multiple times
Debug JSF lifecycle

How to get a JSF resource bundle property value in backing bean?

I am using JSF 2. I am trying to resolve a message bundle reference dynamically the a managed bean property. The value contains the bundle name as well as the key. This is required as the value may come from one of a few different bundles. I have tried many permutations, but the value from the bean seems to be always resolved as a literal String (outputting with EL brackets) and the bundle is never called to resolve and return the value. Any ideas?
I have tried:
#{bundle['key']}
${bundle['key']}
bundle['key']
They are outputted exactly as-is, also in a <h:outputText>. It works fine if I write it directly in the page. My theory is that JSF doesnt realise it has to process the String as an expression. Is there some way to force it?
EL will only be resolved in the view, not in the model. It would otherwise be a huge EL injection attack hole which allows endusers to enter arbitrary EL expressions in input fields and have them resolved. No, you cannot force it in any way.
You need to resolve it yourself. You can do that by either evaluating it programmatically using Application#evaluateExpressionGet():
FacesContext context = FacesContext.getCurrentInstance();
String value = context.getApplication().evaluateExpressionGet(context, "#{bundle['key']}", String.class);
// ...
Or, in this particular case, by just using the ResourceBundle API directly like as JSF is doing under the covers:
ResourceBundle bundle = ResourceBundle.getBundle(basename, FacesContext.getCurrentInstance().getViewRoot().getLocale());
String value = bundle.getString("key");
// ...
Try this..
Resource Bundle referenced by msg
USD=$
xhtml code:
<c:set var="key" value="#{managedBean.currencyCode}" />
<h:outputText value="#{msg[key]}"/>
This should work..

JSF 2.1 ValueExpression in action-attribute

Section 3.1.4 of the JSF 2.1 Specification says that all attributes of standard components are value expression enabled.
I want to assign a value expression to the action attribute of a commandButton:
<h:commandButton value="OK" action="#{myBean.valExp}" />
I also defined corresponding getValExp and setValExp methods in the bean's class.
However my JSF implementation (JBoss 6) takes that expression to be a method expression and thus yields a "method not found" error because there's no valExp()-method.
Am I doing something wrong or is the specification just too sloppy and actually doesn't mean all, but only the non method expression attributes? Or am I misunderstanding the spec?
[Remark: The reason for this question is no actual technical problem but me trying to understand the difference of value and method expressions.]
Value expressions are bound to properties which are exposed by public getter/setter methods.
<h:inputText value="#{bean.value}" />
This requires public T getValue() and public void setValue(T value) methods. Note that the presence of a private T value; property with literally exactly the same name is not mandatory. In pure output components like <h:outputText>, <h:dataTable>, <f:selectItems>, etc, the setter method is also not mandatory.
Method expressions are bound to non-getter/setter methods ("action" methods).
<h:commandButton value="submit" action="#{bean.submit}" />
This requires a public T submit() method where T can eventually be void and the method can eventually take additional arguments, depending on the attribute's method expression signature. You can read the exact details in the view declaration language documentation, for example the <h:inputText>, <h:commandButton> and <f:ajax> ones. Here's an extract of the action and actionListener attribute definitions of the <h:commandButton>:
Name: action
Type: javax.el.MethodExpression (signature must match java.lang.Object
action())
Description: MethodExpression representing the application action to invoke when
this component is activated by the user. The expression must
evaluate to a public method that takes no parameters, and returns an
Object (the toString() of which is called to derive the logical
outcome) which is passed to the NavigationHandler for this
application.
Name: actionListener
Type: javax.el.MethodExpression (signature must match void
actionListener(javax.faces.event.ActionEvent))
Description: MethodExpression representing an action listener method that will be
notified when this component is activated by the user. The
expression must evaluate to a public method that takes an
ActionEvent parameter, with a return type of void, or to a public
method that takes no arguments with a return type of void. In the
latter case, the method has no way of easily knowing where the event
came from, but this can be useful in cases where a notification is
needed that "some action happened".
Yes, I agree that the spec is somewhat sloppy in stating that all attributes support value expressions. Generally, they actually mean that all attributes support expression language as in #{}. From the other hand on, you can also interpret method expressions as if they are just "special" value expressions, although they are not exactly that. I've posted a spec issue report about this with the request to clear up some confusion: issue 1036.

EL variable in JSF ResourceBundle

i read somewhere (don't find it anymore) that i can use EL Expresions in the resource bundle and then use it without changes in *.xhtml files.
some.text=#{someBean.stepsLeft} more
to switch the position of the variable in different languages. But actually it wont work.
I can use Interpolator class to handle the parsing or add some.text.before some.text.after and let one of them empty. I would prefer it to use it without interpolator.interpolate() if possible.
JSF resourcebundles does by default not resolve EL. It however by default supports MessageFormat API in combination with <h:outputFormat> and <f:param>.
some.text = {0} more
with
<h:outputFormat value="#{i18n['some.text']}">
<f:param value="#{someBean.stepsLeft}" />
</h:outputFormat>
You can even explicitly make it a number type so that e.g. 1000 will be displayed as 1,000 or 1.000 depending on the view locale.
some.text = {0,number} more
For more formatting options see thus the MessageFormat API documentation.

JSF - Difference in getting bean instance

HI,
There are many ways to get the bean instances from the JSF context. In the following two way:
Bean bean = (Bean) request.getAttribute("beanName");
and
FacesUtils.getManagedBean("beanName");
What is the difference in above two ways. In which case we have to use either ways. Please clarify me.
Use the first if you're not inside the JSF context (aka the FacesContext), e.g. inside a servlet. The second way is unclear since FacesUtils is not part of standard JSF implementation (it's likely a homegrown or 3rd party library). But if it grabs it by the FacesContext, then it works only when you're already inside the JSF context (i.e. inside a JSF managed bean).

Resources