EL value expressions
Value expressions are probably used the most, and they refer to objects and their properties and attributes. Such expressions are dynamically used to evaluate results or set bean properties at runtime. Through value expressions, you can easily access JavaBeans components, collections, and Java SE enumerated types. Moreover, EL provides a set of implicit objects that can be used to get attributes from different scopes and parameter values. Furthermore, you will see how EL deals with each of these objects.
Note
Value expressions that can read data, but cannot write it are known as rvalue (${}
expressions are always rvalue), while those that can read and write data are known as lvalue (#{}
expressions can be rvalue and/or lvalue).
Referencing a managed bean
Referencing a managed bean is not exactly a useful example, but it is a good point to start. Most commonly, your managed bean will look like the following code (in this case, the bean's class name is PlayersBean
):
@ManagedBean //some scope public class PlayersBean{ ... }
Or, in the CDI version, your managed bean will be as follows:
@Named //some scope public class PlayersBean{ ... }
Or, with an explicit name, your managed bean will be as follows:
@ManagedBean(name = "myPlayersBean") //some scope public class PlayersBean{ ... } @Named(value = "myPlayersBean") //some scope public class PlayersBean{ ... }
Now, for the first two examples, EL refers to the PlayersBean
managed bean, like this—the name is obtained from taking the unqualified class name portion of the fully qualified class name and converting the first character to lowercase as follows:
#{playersBean}
In addition, for the next two examples, EL uses the explicit name as follows:
#{myPlayersBean}
Note
You should use CDI beans whenever possible since they are more flexible than JSF managed beans, and because annotations from javax.faces.bean
will be deprecated in a future JSF version. Therefore, the CDI ones are recommended.
When the referenced managed bean cannot be found in any scope, a null
value will be returned.
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
Referencing a managed bean's properties
As is commonly known, managed beans usually contain private fields, which are accessible through getter and setter methods as bean properties, and some public methods that exploits these properties to serve different logic tasks.
EL expressions that can access these properties contain the dot or square brackets notation, []
. For example, let's suppose that the PlayersBean
managed bean contains two fields defined like the following lines:
private String playerName = "Rafael"; private String playerSurname = "Nadal";
EL can access these fields through their getter methods; therefore, you need to define them as shown in the following code:
public String getPlayerName() { return playerName; } public String getPlayerSurname() { return playerSurname; }
Now, an expression that accesses the playerName
property can use the dot notation (.
) to refer it, as shown in the following line of code:
#{playersBean.playerName}
Alternatively, this expression can use the square brackets notation, []
, as shown in the following line of code:
#{playersBean['playerName']}
Note
JSF evaluates this expression from left to right. First, it searches for playersBean
in all available scopes (such as request, session, and application). Then, the bean is instantiated and the getPlayerName
/getPlayerSurname
getter methods are called (in the case of Boolean properties, the getter method will be named as is
XXX).When you are using the []
notation, you can use simple or double quotes. Just remember to alternate them correctly in cases like the following quotations.
An incorrect quotation (you cannot use double quotes inside double quotes) is:
<h:outputText value="#{playersBean["playerName"]}"/>
An incorrect quotation (you cannot use simple quotes inside simple quotes) is:
<h:outputText value='#{playersBean['playerName']}'/>
A correct quotation (you can use simple quotes in double quotes) is:
<h:outputText value="#{playersBean['playerName']}"/>
A correct quotation (you can use double quotes in simple quotes) is:
<h:outputText value='#{playersBean["playerName"]}'/>
Referencing a managed bean's nested properties
Usually, managed beans use nested properties. Such properties can be accessed by EL using the .
and []
notations multiple times in the same expression.
For example, the PlayersBean
managed bean may represent general data about tennis players, such as name, surname, titles, and finals. More detailed information, such as birthday, birthplace, height, and weight can be represented through a different class named PlayersDetails
. Now, the PlayersBean
managed bean contains a field of type PlayersDetails
, which means that birthday, birthplace, and so on become nested properties of PlayersBean
. Speaking in code lines, the relevant part of the PlayersDetails
class is as follows:
public class PlayerDetails { private Date birthday; private String birthplace; ... public Date getBirthday() { return birthday; } public String getBirthplace() { return birthplace; } ... }
The managed bean of the PlayersBean
class is as follows:
@Named public class PlayersBean{ private String playerName = "Rafael"; private String playerSurname = "Nadal"; private PlayerDetails playerDetails; public String getPlayerName() { return playerName; } public String getPlayerSurname() { return playerSurname; } public PlayerDetails getPlayerDetails() { return playerDetails; } ... }
You already know how to call the playerName
and playerSurname
properties using the .
and []
notations. Next, you can use the same notations to access the birthday
and birthplace
nested properties, as shown in the following code:
#{playersBean.playerDetails.birthday} #{playersBean.playerDetails.birthplace} #{playersBean['playerDetails']['birthday']} #{playersBean['playerDetails']['birthplace']}
Or, you can use both notations in the same expressions, as shown in the following code:
#{playersBean.playerDetails['birthday']} #{playersBean.playerDetails['birthplace']} #{playersBean['playerDetails'].birthday} #{playersBean['playerDetails'].birthplace}
Of course, the PlayerDetails
class can contain its own nested properties and so. In this case, just use the .
and []
notations to get deeper in the hierarchy of objects until you reach the desired property.
In the preceding expressions, JSF search for playersBean
in all the available scopes (request, session, application, and so on) and obtain an instance of it. Afterwards, it calls the getPlayerDetails
method and the getBirthday
method on result of the getPlayerDetails
method (and the same for the birthplace
property).
Referencing Java SE enumerated types
EL can access Java SE enumerated types using a String
literal. For example, let's have an enumerated type defined in PlayersBean
, as shown in the following code:
public enum Plays { Left, Right }; private Plays play; ... play = Plays.Left;//initialization can be done in constructor ... public Plays getPlay() { return play; } ...
You can easily output the play
value as shown in the following line of code:
#{playersBean.play}
To refer to the Plays
constant, Plays.Left
, with an expression, use the String
literal Left
(or Right
for Plays.Right
), for example, you can test whether play
is Left
or Right
, as shown in the following code:
#{playersBean.play == 'Left'} //return true #{playersBean.play == 'Right'}//return false
Referencing collections
Collection items (arrays, lists, maps, sets, and so on) can be accessed from EL expressions by specifying a literal value that can be converted to an integer or the []
notation with an integer and without quotes.
For example, let's suppose that the PlayersBean
managed bean contains an array named titles_2013
that keeps the titles won by a player in 2013. The array is defined as shown in the following code:
private String[] titles_2013 = {"Sao Paulo", "Acapulco", "ATP World Tour Masters 1000 Indian Wells", "Barcelona", ...}; ... public String[] getTitles_2013() { return titles_2013; }
Now, you can access the first title from the array by specifying its position in array, which is 0
:
#{playersBean.titles_2013[0]}
This is equivalent in Java to getting or setting the value for titles_2013[0]
.
However, sometimes you need to iterate over the array instead of accessing a specific item. This can be easily accomplished with the c:forEach
JSTL tag (http://www.oracle.com/technetwork/java/index-jsp-135995.html). The following code snippet iterates over the titles_2013
array and outputs each item (this is a pretty uncommon usage, so do not try it in production):
<c:forEach begin="0" end="${fn:length(playersBean.titles_2013)-1}" var="i"> #{playersBean.titles_2013[i]}, </c:forEach>
You can simplify it as shown in the following code:
<c:forEach var="title" items="#{playersBean.titles_2013}"> <i>#{title}</i>, </c:forEach>
You can also use the <ui:repeat>
tag as shown in the following code:
<ui:repeat var="title" value="#{playersBean.titles_2013}"> <i>#{title}</i>, </ui:repeat>
This tag is detailed in Chapter 12, Facelets Templating, in the Iterating with <ui:repeat> section.
You can use the same approach for every List
. For example, in the case of List
, the expression #{playersBean.titles_2013[0]}
is equivalent in Java to titles_2013.get(0)
and titles_2013.set(0,
some_value)
.
In the case of collections of type key-value (for example, Map
), the EL expressions obtain items by key. For example, let's add a Map
in PlayersBean
that stores some match facts of a player. It can be defined as shown in the following code:
private Map<String, String> matchfacts = new HashMap<>(); ... matchfacts.put("Aces", "12"); matchfacts.put("Double Faults", "2"); matchfacts.put("1st Serve", "70%"); ... public Map<String, String> getMatchfacts() { return matchfacts; }
Now, an EL expression that accesses the item with the key Aces
can be written like the following line of code:
#{playersBean.matchfacts.Aces}
Note
Notice that this approach is not supported on arrays or lists. For example, #{playersBean.titles_2013.0}
is not correct.
When the key is not an acceptable variable name (for example, Double Faults
), you need to use brackets and quotes, as shown in the following code:
#{playersBean.matchfacts["Double Faults"]}
EL implicit objects
JSF provides several objects related to the current request and environment. EL exposes these objects (known as implicit objects) that can be accessed at runtime in a Facelet, servlets, or backing bean—these objects are accessible through value expressions and are managed by the container. For each expression, EL first checks if the value of the base is one of these implicit objects, and, if it is not, then it will check beans in progressively wider scopes (from request to view, and finally to application scope).
Note
In EL, the part of the expression before the dot or the square bracket is named base and it usually indicates where the bean instances should be located. The part after the first dot, or the square bracket, is called a property and is recursively cracked in smaller parts, which represents the bean's properties to get from the base.
You can see a short overview of these objects in the following table: