JSF: Bean method call with parameter - jsf

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.

Related

jsf methods expression valuechanged event don't work or work different in inputtext and selectOneMenu

i'm new with jsf technology and use of managed bean.
I'm reading the Java Platform, Enterprise Edition The Java EE Tutorial release 7 but it seems to be not clear, i have different problem how in example below :
<h:selectOneMenu value="#{user.age}" onchange="submit()" valueChangeListener="#{user.ageChanged}">
<f:selectItems value="#{user.ages}" />
<f:converter converterId="javax.faces.Integer"/>
</h:selectOneMenu>
<h:inputText id="name" value="#{user.name}" required="true" validator="#{user.validateName}" valueChangeListener="#{user.nameChanged}" onchange ="submit()" />
the first one do the job, but the second not it displays:
'managedBean.User' does not have the property nameChanged.
but ageChanged is not a property but the first example do the job
but i'm using method expression to refers method nameChanged that it's present on the bean user,
i'm confusing, too with use or not of the bracket on methods expression:
valueChangeListener="#{user.nameChanged}" or valueChangeListener="#{user.nameChanged()}" what is the properly way to use methods expression?
i say this cause in another example having method with no parameters, the two approaches had different behave, first the same error about property missing, the second Apparently worked.
any help? a speak about method expressions it's appreciated to. thank you.

Calling bean methods with arguments from JSF pages

Is it possible to call bean methods & directly pass parameters to them from the view instead of requiring to first set the bean properties and then call methods without arguments using the commandButton or similar ?
I have a list of items with each item having a list of actions. To reduce the state, I am using a single primefaces remoteCommand, in place of several commandButton(s). On getting a action trigger from the view, I would call the remoteCommand from javascript but since the remoteCommand is one but used for multiple items thus I need to pass the id of the item as well. I am wondering if there is a way to pass the id of the item to the bean method directly as an argument instead of first setting it as a bean property ? Is there any way to do so ?
Actually I am looking at a better way to deal with multiple commandButtons on a page when there's a long list of items on the page.
Suggestions ? Thanks.
Using JSF 2.1.6 Mojarra with Primefaces 3.0RC1
Passing method arguments is supported since EL 2.2 which is part of Servlet 3.0. So if your webapp runs on a Servlet 3.0 compatible container (Tomcat 7, Glassfish 3, etc) with a web.xml declared conform Servlet 3.0 spec (which is likely true as you're using JSF 2.1 which in turn implicitly requires Servlet 3.0), then you will be able to pass method arguments to bean action methods in the following form:
<h:commandButton value="Submit" action="#{bean.submit(item.id)}" />
with
public void submit(Long id) {
// ...
}
You can even pass fullworthy objects along like as:
<h:commandButton value="Submit" action="#{bean.submit(item)}" />
with
public void submit(Item item) {
// ...
}
If you were targeting a Servlet 2.5 container, then you could achieve the same by replacing the EL implementation by for example JBoss EL which supports the same construct. See also Invoke direct methods or methods with arguments / variables / parameters in EL.
Yes, it is.
<h:commandButton action="#{bean.method(object)}" />
See this http://www.mkyong.com/jsf2/4-ways-to-pass-parameter-from-jsf-page-to-backing-bean/
You can call ManagedBean methods with arguments like this.
<h:commandButton actionListener="#{stateBean.delete(row.stateID)}"
value="Delete" id="btnDeleteS">
<f:ajax event="action" execute="#form" render="#form"/>
</h:commandButton>
The corresponding ManagedBean would be like this.
#ManagedBean
#RequestScoped
public class StateBean
{
#EJB
private RemoteInterface obj=null;
public void delete(String stateID)
{
//Code stuff here.
}
}
You can also directly set the value of ManagedBean properties using <f:setPropertyActionListener></f:setPropertyActionListener> like this.
<h:commandButton value="Delete" id="btnDeleteS">
<f:setPropertyActionListener target="#{stateBean.someProperty}"
value="#{someValue}"/>
<f:ajax event="action" execute="#form" render="#form"/>
</h:commandButton>

Populate by code SelectOneMenu based on custom meta-data in attributes

I need a solution to populate by code SelectOneMenu using some meta-data specified as an attribute to this component.
Here is the detail of my requirement.
1) The developer would specify some thing like this:
<h:selectOneMenu id="someComponent" value="#{someController.someModel.someField}">
<f:attribute name="entity" value="somepackage.SomeEntity" />
</h:selectOneMenu>
2) When the page containing the above is requested for the first time, the server should be able to read the 'entity' attribute
3) Once the 'entity' is read, the server will do the needful to populate dynamically 'someComponent'.
I have no issue with the code that should use the 'entity' attribute and generate the content to be show in 'someComponent'. My issue is to found the appropriate place to call efficiently this code.
I have tried the PhaseEventListener for 'After Render Response Phase' but with no luck. It looks like I'm missing something fundamental as I'm new to JSF.
Have someone went through the same experiment?
Thank you in advance.
Younes Ouadi
If you target an EL 2.2 container which supports invoking methods with arguments and/or supply JBoss EL with your webapp so that it works on EL 2.1 as well, then it should be possible with the following construct:
<h:selectOneMenu id="someComponent" value="#{someController.someModel.someField}">
<f:selectItems value="#{someProvider.selectItems('somepackage.SomeEntity')}" />
</h:selectOneMenu>
with
public List<SelectItem> getSelectItems(String className) {
// ...
}
I'd introduce some lazy loading and/or request-based caching mechanism as well as a getter can be called more than once during bean's life.

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

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