SeamFramework.orgCommunity Documentation

Chapter 35. JBoss EL

35.1. Parameterized Expressions
35.1.1. Usage
35.1.2. Limitations and Hints
35.2. Projection

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.

Standard EL 2.1 does not allow you to use a method with user defined parameters — of course, JSF listener methods (e.g. a valueChangeListener) take parameters provided by JSF. Standard EL 2.2, which is in Java EE 6, allows it now. So you don't have to use JBoss EL enhancements.

You can still use JBoss EL instead of standard EL 2.2 from Java EE 6 by setting up com.sun.faces.expressionFactory in web.xml:

<context-param>
    <param-name>com.sun.faces.expressionFactory</param-name>
    <param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>

JBoss EL and EL 2.2 removed this restriction. For example:


<h:commandButton action="#{hotelBooking.bookHotel(hotel)}" value="Book Hotel"/>
@Name("hotelBooking")

public class HotelBooking 
{   
   public String bookHotel(Hotel hotel) 
   {
      // Book the hotel
   }
}

Just as in calls to method from Java, parameters are surrounded by parentheses, and separated by commas:


<h:commandButton action="#{hotelBooking.bookHotel(hotel, user)}" value="Book Hotel"/>

The parameters hotel and user will be evaluated as value expressions and passed to the bookHotel() method of the component.

Any value expression may be used as a parameter:


<h:commandButton 
   action="#{hotelBooking.bookHotel(hotel.id, user.username)}" 
   value="Book Hotel"/>

It's important to fully understand how this extension to EL works. When the page is rendered, the parameter names are stored (for example, hotel.id and user.username), and evaluated (as value expressions) when the page is submitted. You can't pass objects as parameters!

You must ensure that the parameters are available not only when the page is rendered, but also when it is submittedIf the arguments can not be resolved when the page is submitted the action method will be called with null arguments!

You can also pass literal strings using single quotes:


<h:commandLink action="#{printer.println('Hello world!')}" value="Hello"/>

Unified EL also supports value expressions, used to bind a field to a backing bean. Value expressions use JavaBean naming conventions and expect a getter/setter pair. Often JSF expects a value expression where only retrieval (get) is needed (e.g. the rendered attribute). Many objects, however, don't have appropriately named property accessors or require parameters.

JBoss EL removes this restriction by allowing values to be retrieved using the method syntax. For example:


<h:outputText value="#{person.name}" rendered="#{person.name.length() > 5}" />

You can access the size of a collection in a similar manner:

#{searchResults.size()}

In general any expression of the form #{obj.property} would be identical to the expression #{obj.getProperty()}.

Parameters are also allowed. The following example calls the productsByColorMethod with a literal string argument:

#{controller.productsByColor('blue')}

When using JBoss EL you should keep the following points in mind:

JBoss EL supports a limited projection syntax. A projection expression maps a sub-expression across a multi-valued (list, set, etc...) expression. For instance, the expression:

#{company.departments}

might return a list of departments. If you only need a list of department names, your only option is to iterate over the list to retrieve the values. JBoss EL allows this with a projection expression:

#{company.departments.{d|d.name}}

The subexpression is enclosed in braces. In this example, the expression d.name is evaluated for each department, using d as an alias to the department object. The result of this expression will be a list of String values.

Any valid expression can be used in an expression, so it would be perfectly valid to write the following, assuming you had a use for the lengths of all the department names in a company:

#{company.departments.{d|d.size()}}

Projections can be nested. The following expression returns the last names of every employee in every department:

#{company.departments.{d|d.employees.{emp|emp.lastName}}}

Nested projections can be slightly tricky, however. The following expression looks like it returns a list of all the employees in all the departments:

#{company.departments.{d|d.employees}}

However, it actually returns a list containing a list of the employees for each individual department. To combine the values, it is necessary to use a slightly longer expression:

#{company.departments.{d|d.employees.{e|e}}}

It is important to note that this syntax cannot be parsed by Facelets or JSP and thus cannot be used in xhtml or JSP files. We anticipate that the projection syntax will change in future versions of JBoss EL.