How to pass a method argument to getter? - jsf

I want to use a datalist
<rich:dataList value="#{bean.itemsOnLevel}" var="item">
<h:outputText value="#{item.value}" />
</rich:dataList>
but my getter needs a parameter
public List getItemsOnLevel(int level);
how can I pass the level?

If you're already targeting a Servlet 3.0 compatible container (Tomcat 7, Glassfish 3, JBoss 6, etc) with a Servlet 3.0 compatible web.xml in your webapp, then you can make use of the new EL 2.2 feature of invoking methods with arguments:
<rich:dataList value="#{bean.getItemsOnLevel(1)}" var="item">
<h:outputText value="#{item.value}" />
</rich:dataList>
If you're however targeting an older Servlet 2.5 compatible container (Tomcat 6, Glassfish 2, JBoss 4/5, etc), then your best bet is to install JBoss EL to achieve the same. See also this answer for details: Invoke direct methods or methods with arguments / variables / parameters in EL

Related

How to pass parameters into a p:commandbutton? [duplicate]

How can I in JSF 2.0 invoke direct methods or methods with arguments / variables / parameters in EL?
For example, getting the list size in EL:
<h:outputText value="#{bean.list.size()}" />
Or invoking an action method with arguments:
<h:commandButton value="edit" action="#{bean.edit(item)}" />
This does not seem to work in my environment. It doesn't seem to like parentheses.
javax.el.ELException: Error Parsing: #{bean.list.size()}
com.sun.el.parser.ParseException: Encountered "("
In standard EL prior to EL 2.2 from Java EE 6 you cannot directly invoke methods like
#{bean.method()} nor invoke methods with arguments like #{bean.method(arg1, arg2).
If upgrading to a EL 2.2 / Java EE 6 compliant container (Tomcat 7, Glassfish 3, JBoss AS 6, etc) is not an option and you're currently using EL 2.1 / Java EE 5 (Tomcat 6, Glassfish 2, JBoss AS 4, etc), then your best bet is to install JBoss EL. JBoss EL is an EL 2.1 compliant implementation which supports the same features as EL 2.2. Installing JBoss EL is a matter of putting the jboss-el.jar in /WEB-INF/lib and adding the following to the web.xml, assuming that you're using Mojarra:
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
Or, when you're using MyFaces:
<context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
An alternative for your particular case is to use JSTL's fn:length:
<h:outputText value="#{fn:length(bean.list)}" />
Another alternative is to add a getter to the bean which returns List#size() or in some specific cases a custom EL function.
Please note thus that invoking methods with arguments in EL is not a JSF 2.0 specific feature. It's an EL 2.2 specific feature. EL 2.2 is part of Java EE 6, which JSF 2.0 is also part of. So it look like a JSF 2.0 specific feature, but it isn't. JSF 2.0 is backwards compatible with Servlet 2.5 / EL 2.1 which lacks this feature. On the other hand, JSF 1.x is forwards compatible with Servlet 3.0 / EL 2.2, so it would also be possible to use this feature in JSF 1.x then, also using JBoss EL on Servlet 2.5 / EL 2.1.
BalusC's answer is correct, however, when you use maven, you should exclude el-api 1.0 transitive dependency like this:
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-el</artifactId>
<version>2.0.0.GA</version>
<!-- exclude el-api 1.0 transitive dependency -->
<exclusions>
<exclusion>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
</exclusion>
</exclusions>
</dependency>

How to display value of List#size() in JSF EL?

I'd like to know if there's a way to bind the returned value of a method into a JSF component.
I'll explain myself better.
Let's say I have a class like this:
public class Document {
private List<Attachment> attachments;
//getter and setter here
}
this class is exposed to jsf through a registered managed bean in a property called currentDocument, and used in a jsf this way
<h:outputText value="#{myManagedBean.currentDocument.attachment.size}" />
This isn't correct, I know. But what is the correct way to do this?
Am I supposed to create an attribute on the Document class, let's say numberOfAttachments, and bind to that, or there's a way to bind directly on a method's return value?
If you're running an EL 2.2 capable container (Tomcat 7, Glassfish 3, JBoss AS 6 or newer, all implementing Servlet 3.0), or are using JBoss EL, then you should be able to invoke non-getter methods by EL:
<h:outputText value="#{myManagedBean.currentDocument.attachment.size()}" />
An alternative is to use JSTL fn:length():
<html xmlns:fn="http://java.sun.com/jsp/jstl/functions" ...>
...
<h:outputText value="#{fn:length(myManagedBean.currentDocument.attachment)}" />
If none of that is possible for you for some reason, then your best bet is to create an EL function yourself
<h:outputText value="#{my:size(myManagedBean.currentDocument.attachment)}" />
or to add an extra getter method to #{myManagedBean} which returns exactly that.
<h:outputText value="#{myManagedBean.currentDocumentAttachmentSize}" />
See also:
Invoke direct methods or methods with arguments / variables / parameters in EL

Basic JSF: is it possible to SET a property value in EL?

I need to do something like this:
<a4j:support even="onclick" action="#{myBean.myProperty = null}"/>
I would like to know if this is possible and which would be the proper syntax if so.
If you're running an EL 2.2 capable container (Tomcat 7, Glassfish 3, JBoss AS 6, etc and newer, with a web.xml declared conform at least Servlet 3.0), or are using JBoss EL (your seam tag suggests that you are using it...), then you should be able to invoke methods with arguments in EL:
<a4j:support event="onclick" action="#{myBean.setMyProperty(null)}"/>
An alternative is using <f:setPropertyActionListener>, this is supported in JSF 1.2 as well:
<a4j:support event="onclick" />
<f:setPropertyActionListener target="#{myBean.myProperty}" value="#{null}" />
Bean setter methods are called on form submission but based on your example why not do something like:
<a4j:support event="onclick" action="#{myBean.resetMyProperty}"/>
And in your bean your resetMyProperty method would set the myProperty to null

JSF: Bean method call with parameter

I can't get method calls with parameters to work in JSF 2.0 (MyFaces) and Tomcat 6.
This is how I try it:
<f:selectItems var="item" value="#{bla.someList}
itemValue="#{item.value1}"
itemLabel="#{item.value2}">
<f:param name="param1" value="0" />
</f:selectItems>
I can't define the method like this, right? And why not?
getSomeList(int a)
So this is what I tried:
getSomeList() {
Integer a = Integer.parseInt(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("param1"));
return doSomething(a);
}
And this is what I get:
java.lang.NumberFormatException: null
java.lang.Integer.parseInt(Integer.java:417)
I would be very grateful if someone helped me out. Thanks!
UPDATE: Ah, it worked with #{bla.getSomeList(0)}!
I can't define the method like this, right?
getSomeList(int a)
No.
And why not?
Because you're using old Tomcat 6 which doesn't support EL 2.2 where this feature was introduced.
And this is what I get:
java.lang.NumberFormatException: null
java.lang.Integer.parseInt(Integer.java:417)
Because there it is null. The <f:param> works in links/buttons only, not on plain components.
In order to get method calls in EL to work, you need to upgrade to a Servlet 3.0 / EL 2.2 capable container like Tomcat 7, or to replace Tomcat 6's default EL 2.1 implementation by one which supports parameterized method calls. For detail see this answer. Once done that, you can use
<f:selectItems value="#{bla.getSomeList(0)}" ... />
An alternative is to replace List by Map, which can be a custom implementation which does (lazy) loading on get() method.
public Map<String, List<Something>> getSomeMap() {
return someCustomLazyLoadingMap;
}
with
<f:selectItems value="#{bla.someMap.keyName}" ... />
Try using
<f:selectItems var="item" value="#{bla.someList(0)} itemValue="#{item.value1}" itemLabel="#{item.value2}"/>
This works for some implementations of JSF.

String concatenation in EL for dynamic ResourceBundle key

I have a resource bundle with entries like these:
entry1=value1
entry2=value2
entry3=value3
In my JSF page I'm trying to use these keys dynamically. The ID of the entry is coming from a managed bean. I think it should be something like this:
<h:outputText value="#{msg['entry' managedBean.entryIndex]}"/>
How can I achieve this?
If you're already on Servlet 3.1 / EL 3.0 (Tomcat 8, WildFly 8, GlassFish 4, etc), make use of new EL 3.0 += operator:
<h:outputText value="#{msg['entry' += managedBean.entryIndex]}" />
If you're only on Servlet 3.0 / EL 2.2 (Tomcat 7, JBoss AS 6/7, GlassFish 3, etc), make use of new EL 2.2 ability to directly invoke methods such as String#concat():
<h:outputText value="#{msg['entry'.concat(managedBean.entryIndex)]}" />
If you're even not on Servlet 3.0 / EL 2.2 yet, make use of <c:set> to create another variable with the desired EL expression inlined:
<c:set var="key" value="entry#{managedBean.entryIndex}" />
<h:outputText value="#{msg[key]}" />
This should solve your issue:
<h:outputText value="#{msg['entry'.concat(managedBean.entryIndex)]}"/>
Here's what worked for me : concat outside of []
<h:outputText value="#{msg['entry'].concat(managedBean.entryIndex)}" />
I think you'll have to write a facelets function concat(str1, str2).

Resources