How to call a method with a parameter in JSF - jsf

I' ve a JSF page that shows the content of a folder (really it's a dropbox's account content).
I'm using a dataTable to render the content of a ListArray object:
<h:dataTable style="text-align: left" width="600" var="dContent" value="#{backedBean.contents}">
<h:column>
<f:facet name="header">
<f:verbatim>NAME</f:verbatim>
</f:facet>
<h:commandButton value="#{dContent.fileName}" action="#{backedBean.updateContents(dContent)}"/>
</h:column>
<h:column>
<f:facet name="header">
<f:verbatim>SIZE</f:verbatim>
</f:facet>
<h:outputText value="#{dContent.size}"/>
</h:column>
</h:dataTable>
But when I run this page I obtain the following error:
/browse.xhtml #34,110 action="#{backedBean.updateContents(dContent)}"
Error Parsing: #{backedBean.updateContents(dContent)} ...
... Caused by: org.apache.el.parser.ParseException: Encountered "
"(" "( "" at line 1, column 28. Was expecting one of:
"}" ...
"." ...
"[" ...
">" ...
"gt" ...
"<" ...
"lt" ...
">=" ...
"ge" ... ... ...
The funny thing is that Netbeans is able to autocomplete the method name so I image that my backend bean is ok. The problem occurs only when I call a method with a parameter.
Any ideas?
Many thanks

Passing method arguments was introduced in EL 2.2. So this is only possible if you're running on a Servlet 3.0 / EL 2.2 capable container like Tomcat 7, Glassfish 3, JBoss AS 6, etc and your web.xml is been declared as per Servlet 3.0 specification.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
>
<!-- Config here -->
</web-app>
If you aren't, then check this answer for alternatives with regard to obtaining current row in datatables, or this answer with regard to replacing the EL implementation by one which supports passing method arguments so that you can use it on Servlet 2.5 / EL 2.1 containers as well.

Jboss Seam can also help to get the feature.
Seam uses JBoss EL which provides an extension to the standard Unified Expression Language (EL). JBoss EL provides a number of enhancements that increase the expressiveness and power of EL expressions.
Example:
pass literal strings using single quotes:
<h:commandLink action="#{printer.println('Hello world!')}" value="Hello"/>
or
for dynamic value
<h:commandButton action="#{hotelBooking.bookHotel(hotel)}" value="Book Hotel"/>
Limitation:
JBoss EL can't currently be used with JSP 2.1 as the compiler rejects expressions with parameters in. So, if you want to use this extension with JSF 1.2, you will need to use Facelets. The extension works correctly with JSP 2.0.

There has actually been a "hack" way of doing this since JSF 1.0. You just create a method on your backing bean that returns a Map, and you can use JSF EL to pass whatever object you want to that method, because JSF thinks that you are passing the key to the map.
Meanwhile, in your backing bean method you actually return an "imposter" map instance that is not really a map at all, whose get() method delegates to the method you wanted to call. In your .xhtml or .jsp file then you can use the square bracket notation to pass the variable.
Extending HashMap is one way to make the imposter map easy to define -- succinct enough to use an anonymous inner class that way.
This is a hack, but it has worked well for me in the past.

Related

ui:param value loses its value in included website (included by ui:include)

I have a JSF XHTML site which includes another JSF XHTML site (example.xhtml) via ui:include:
<p:dataTable> ...
<ui:include src="example.xhtml">
<ui:param name="sortByParam" value="MyValue"/> ...
Inside the example.xhtml site I use parameters like:
<ui:composition>
<p:column sortBy="#{sortByParam}" ... />
This works at first glance flawless. But when I navigate forth and back between this and other sites the site breaks at some time - couldn't find a pattern so far. Because the attribute value of sortBy in example.xhtml gets actually passed to my bean as the string #{sortByParam} - not the value of the parameter (would be MyValue in this example).
At some point in time it stops evaluating the passed parameter and passes the attribute as it is directly to my Java code.
How do I stop that? Is this a bug?
I use Primefaces 7.0.3, Mojarra: 2.3.2, Java EE 8, Glassfish 5.0

How to pass argument to method in ui:repeat or c:forEach [duplicate]

I have just a question in passing parameters on backing beans method.
I would like pass an EL value between a method parameters like:
<p:selectOneMenu id="somsgroup" value="#{store_itemController.filter_sgroup}">
<f:selectItems value="#{commonDataFunctions.getItemByName('store_sgroup', 'id', 'title', '[tb:store_sgroup][fd:title]=${store_itemController.filter_group}', '[tb:store_sgroup][fd:title]', true)}"/>
</p:selectOneMenu>
it seems like ${store_itemController.filter_group} it is not translated because the method receives ${store_itemController.filter_group} just like a string.
Is there a solution?
You can indeed not nest EL expressions this way. EL expressions can only be inlined.
You can use <c:set> to create a new variable wherein the desired expression is inlined in the desired value and then reuse this variable as argument of another EL expression.
xmlns:c="http://java.sun.com/jsp/jstl/core"
...
<c:set var="filterGroup" value="[tb:store_sgroup][fd:title]=#{store_itemController.filter_group}" scope="request" />
...
<f:selectItems value="#{commonDataFunctions.getItemByName('store_sgroup', 'id', 'title', filterGroup, '[tb:store_sgroup][fd:title]', true)}"/>
I would like to suggest to use JBoss EL. If so, you need to configure as below in web.xml.
Download jar file here and reference for previous post.
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>

JSF 2.2 - everything inside ui:repeat is evaluated, although rendered = "false"

I'm currently migrating a web application from JSF 1.2/Richfaces 3.3.3 to JSF 2.2 For data iteration, we used a4j:repeat from Richfaces. I now want to change the iterators to ui:repeat, because we want to throw out Richfaces.
However, I came across a very strange behaviour. Imagine a code snippet like this (simplified from the original):
<ui:repeat id="criterions" var="criterion" value="#{AdvancedSearchBean.criterionList}">
<h:panelGroup rendered="#{criterion.searchCriterion.displayType == 'PERSON'}">
<h:inputText value="#{criterion.searchString}"/>
</h:panelGroup>
</ui:repeat>
The part inside the panelGroup is evaluated, although the rendered condition definitely evaluates to false. If I change ui:repeat to a4j:repeat, it works fine, the part inside the panelGroup is NOT evaluated.
This is a real problem for our code, as the "criterion" variable can contain different objects (extending the same superclass). In this case, the criterion object does not contain a property with the name "searchString" (because it is not of type "PERSON") -> an error is thrown.
Can anyone explain this behaviour or has a solution?
I'm using the JSF version integrated in WildFly 8.0.0.final (Mojarra 2.2.5-jbossorg-3)
Thanks
Markus

How to employ internationalization for JSF bean properties?

I would like to display an internationalized message in the place holder below. All examples I'm hitting, work with a message bundle defined in faces-config and simply use that bundle name. But that works only when we know what message key to use. This isn't the case here.
Consider this basic example:
<h:dataTable border="1" value="#{indexBean.webAdminCatalogList}" var="menuItem">
<h:column>#{message key here}</h:column>
</h:dataTable>
The code above loops through a list. Each menuItem variable contains a titleMessageCode which corresponds to a field in the bundle properties files. How do you go about fetching a message using menuItem.titleMessageCode? Is there a special JSF tag or are such internationalized labels prepared when constructing the bean?
You can use the brace notation #{map[dynamicKey]} to use a dynamic variable as map key. Given a bundle name of text, here's an example:
<h:dataTable border="1" value="#{indexBean.webAdminCatalogList}" var="menuItem">
<h:column>#{text[menuItem.titleMessageCode]}</h:column>
</h:dataTable>
Note that this is not specific to JSF, but to EL. Those #{} things are not part of JSF, they are part of EL (Expression Language). JSF just happens to make use of it. See also our EL wiki page.

JSF accessing backing map object

I have a jsp subview page that I have passed a parameter to and I want to then pass that parameter to a map's get() method that is stored in a session bean.
Ex:
<h:panelGrid id="panelGrid1" rendered="#{MySessionBean[param.id].showPanelGrid1}">
...
</h:panelGrid>
In the above example MySessionBean implements the Map interface and I have my own custom get method that will create an object and put it in the map if none exists for the key [params.id]. When I run the code in debug mode my get method for MySessionBean never gets called and my panel is always rendered. Am I not passing parameters correctly? Or accessing the parameter passed to the subview correclty?
Here is how I passed the parameter to this subview:
<f:subview id="subview1">
<jsp:include page="/MyTemplatePage.jsp">
<jsp:param name="id" value="staticUniqueId1"/>
</jsp:include>
</f:subview>
The reason I'm trying to do this is so I can include this template subview multiple times in a single page so that each instance won't have the same backing bean objects. Thus using a map in the session and passing it an id to gain access to the backing beans for each instance.
Also, I am limited JSF 1.2, JSTL 1.1, JBoss 4.0.4. So I can't use answers that use RichFaces or JSF 2.
EDIT: 11/22/11 11:23
I Replaced the [param.id] with a static string value.
<h:panelGrid id="panelGrid1" rendered="#{MySessionBean.MY_TEMP_VAL.showPanelGrid1}">
...
</h:panelGrid>
And everything worked. It triggered my map get method and accessed the session beans and everything. So it is clearly not liking the whole using [params.id] passing to the map object. Not sure what to do from here.
In JSF2 the proper and easy solution would be to use composite components. Since you are stuck with JSF 1.2 and jsp you could use tag files instead. These are like regular jsps but with the extension tag or tagx and placed under WEB-INF/tags. I'm using the xml syntax in the example below, in a file name example.tagx:
<jsp:root version="2.1"
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:h="http://java.sun.com/jsf/html">
<jsp:directive.attribute name="myBean"
required="true"
rtexprvalue="false"
deferredValue="true"
deferredValueType="com.example.MyBean"/>
<h:panelGrid id="panelGrid1" rendered="#{myBean.showPanelGrid1}">
...
</h:panelGrid>
</jsp:root>
In a jspx you then have to declare the namespace like xmlns:myTags="urn:jsptagdir:/WEB-INF/tags/", in a jsp the syntax would be:
<%#taglib tagdir="/WEB-INF/tags" prefix="myTags" %>
The custom tag can then be used multiple times on a page and the right backing bean can be passed as an attribute like this:
<myTags:example myBean="#{myBeanInstance1}" />
Edit: You might also need a file WEB-INF/tags/implicit.tld to specify the version:
<?xml version = '1.0' encoding = 'UTF-8'?>
<taglib xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1" xmlns="http://java.sun.com/xml/ns/javaee">
<tlib-version>2.1</tlib-version>
</taglib>

Resources