JBoss.com Enterprise Documentation

- Prev
- Next

## Chapter 30. JBoss EL

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.

## 30.1. Parameterized Expressions

Standard EL 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.

JBoss EL removes 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

       }

    }

### 30.1.1. Usage

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')}

### 30.1.2. Limitations and Hints

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

- Incompatibility with JSP 2.1 — 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.

- Use inside iterative components — Components like `<c:forEach />` and `<ui:repeat />`iterate over a List or array, exposing each item in the list to nested components. This works great if you are selecting a row using a `<h:commandButton />` or `<h:commandLink />`:

      @Factory("items")

      public List<Item> getItems() {

         return entityManager.createQuery("select ...").getResultList();

      }

      <h:dataTable value="#{items}" var="item">

         <h:column>

            <h:commandLink value="Select #{item.name}" action="#{itemSelector.select(item})" />

         </h:column>

      </h:dataTable>

  However if you want to use `<s:link />` or `<s:button />` you must expose the items as a `DataModel`, and use a `<dataTable />` (or equivalent from a component set like `<rich:dataTable />` ). Neither `<s:link />` or `<s:button />` submit the form (and therefore produce a bookmarkable link) so a "magic" parameter is needed to recreate the item when the action method is called. This magic parameter can only be added when a data table backed by a `DataModel` is used.

- Calling a `MethodExpression` from Java code — Normally, when a `MethodExpression` is created, the parameter types are passed in by JSF. In the case of a method binding, JSF assumes that there are no parameters to pass. With this extension, we can't know the parameter types until after the expression has been evaluated. This has two minor consequences:

  - When you invoke a `MethodExpression` in Java code, parameters you pass may be ignored. Parameters defined in the expression will take precedence.

  - Ordinarily, it is safe to call `methodExpression.getMethodInfo().getParamTypes()` at any time. For an expression with parameters, you must first invoke the `MethodExpression` before calling `getParamTypes()`.

  Both of these cases are exceedingly rare and only apply when you want to invoke the `MethodExpression` by hand in Java code.

## 30.2. Projection

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.

- PrevChapter 29. Seam JSF controls
- Top of page
- Front page
- NextChapter 31. Testing Seam applications