forked from seam2/jboss-seam
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Elenhancements.xml
executable file
·285 lines (239 loc) · 12.3 KB
/
Elenhancements.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
<chapter id="elenhancements">
<title>JBoss EL</title>
<para>
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.
</para>
<section>
<title>Parameterized Expressions</title>
<para>
Standard EL 2.1 does not allow you to use a method with user defined
parameters — of course, JSF listener methods (e.g. a
<literal>valueChangeListener</literal>) take parameters provided by JSF.
<ulink url="http://docs.oracle.com/javaee/6/tutorial/doc/gjddd.html">Standard EL 2.2</ulink>,
which is in Java EE 6, allows it now. So you don't have to use JBoss EL enhancements.
</para>
<para>You can still use JBoss EL instead of standard EL 2.2 from Java EE 6 by
setting up <literal>com.sun.faces.expressionFactory</literal> in <filename>web.xml</filename>:
<programlisting><![CDATA[<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>]]></programlisting>
</para>
<para>
JBoss EL and EL 2.2 removed this restriction. For example:
</para>
<programlisting role="XHTML"><![CDATA[<h:commandButton action="#{hotelBooking.bookHotel(hotel)}" value="Book Hotel"/>]]></programlisting>
<programlisting role="JAVA"><![CDATA[@Name("hotelBooking")
public class HotelBooking
{
public String bookHotel(Hotel hotel)
{
// Book the hotel
}
}]]></programlisting>
<section>
<title>Usage</title>
<para>
Just as in calls to method from Java, parameters are surrounded by
parentheses, and separated by commas:
</para>
<programlisting role="XHTML"><![CDATA[<h:commandButton action="#{hotelBooking.bookHotel(hotel, user)}" value="Book Hotel"/>]]></programlisting>
<para>
The parameters <literal>hotel</literal> and <literal>user</literal>
will be evaluated as value expressions and passed to the
<literal>bookHotel()</literal> method of the component.
</para>
<para>
Any value expression may be used as a parameter:
</para>
<programlisting role="XHTML"><![CDATA[<h:commandButton
action="#{hotelBooking.bookHotel(hotel.id, user.username)}"
value="Book Hotel"/>]]></programlisting>
<para>
It's important to fully understand how this extension to EL works.
When the page is rendered, the parameter <emphasis>names</emphasis>
are stored (for example, <literal>hotel.id</literal> and
<literal>user.username</literal>), and evaluated (as value
expressions) when the page is submitted. You can't pass objects as
parameters!
</para>
<para>
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 <literal>null</literal> arguments!
</para>
<para>
You can also pass literal strings using single quotes:
</para>
<programlisting role="XHTML"><![CDATA[<h:commandLink action="#{printer.println('Hello world!')}" value="Hello"/>]]></programlisting>
<para>
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
<literal>rendered</literal> attribute). Many objects, however, don't
have appropriately named property accessors or require parameters.
</para>
<para>
JBoss EL removes this restriction by allowing values to be retrieved
using the method syntax. For example:
</para>
<programlisting role="XHTML"><![CDATA[<h:outputText value="#{person.name}" rendered="#{person.name.length() > 5}" />]]></programlisting>
<para>
You can access the size of a collection in a similar manner:
</para>
<programlisting>#{searchResults.size()}</programlisting>
<para>
In general any expression of the form #{obj.property} would be
identical to the expression #{obj.getProperty()}.
</para>
<para>
Parameters are also allowed. The following example calls the
<literal>productsByColorMethod</literal> with a literal string
argument:
</para>
<programlisting>#{controller.productsByColor('blue')}</programlisting>
</section>
<section>
<title>Limitations and Hints</title>
<para>
When using JBoss EL you should keep the following points in mind:
</para>
<itemizedlist>
<listitem>
<para>
<emphasis>Incompatibility with JSP 2.1</emphasis> —
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.
</para>
</listitem>
<listitem>
<para>
<emphasis>Use inside iterative components</emphasis> —
Components like <literal><c:forEach /></literal> and
<literal><ui:repeat /></literal>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
<literal><h:commandButton /></literal> or
<literal><h:commandLink /></literal>:
</para>
<programlisting role="JAVA"><![CDATA[@Factory("items")
public List<Item> getItems() {
return entityManager.createQuery("select ...").getResultList();
}]]></programlisting>
<programlisting role="XHTML"><![CDATA[<h:dataTable value="#{items}" var="item">
<h:column>
<h:commandLink value="Select #{item.name}" action="#{itemSelector.select(item})" />
</h:column>
</h:dataTable>]]></programlisting>
<para>
However if you want to use <literal><s:link /></literal>
or <literal><s:button /></literal> you
<emphasis>must</emphasis> expose the items as a
<literal>DataModel</literal>, and use a
<literal><dataTable /></literal> (or equivalent from a
component set like <literal><rich:dataTable /></literal>
). Neither <literal><s:link /></literal> or
<literal><s:button /></literal> 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 <literal>DataModel</literal> is used.
</para>
</listitem>
<listitem>
<para>
<emphasis>Calling a <literal>MethodExpression</literal> from
Java code</emphasis> — Normally, when a
<literal>MethodExpression</literal> 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:
</para>
<itemizedlist>
<listitem>
<para>
When you invoke a <literal>MethodExpression</literal> in
Java code, parameters you pass may be ignored.
Parameters defined in the expression will take
precedence.
</para>
</listitem>
<listitem>
<para>
Ordinarily, it is safe to call
<literal>methodExpression.getMethodInfo().getParamTypes()</literal>
at any time. For an expression with parameters, you must
first invoke the <literal>MethodExpression</literal>
before calling <literal>getParamTypes()</literal>.
</para>
</listitem>
</itemizedlist>
<para>
Both of these cases are exceedingly rare and only apply when
you want to invoke the <literal>MethodExpression</literal> by
hand in Java code.
</para>
</listitem>
</itemizedlist>
</section>
</section>
<section>
<title>Projection</title>
<para>
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:
</para>
<programlisting>#{company.departments}</programlisting>
<para>
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:
</para>
<programlisting>#{company.departments.{d|d.name}}</programlisting>
<para>
The subexpression is enclosed in braces. In this example, the
expression <literal>d.name</literal> is evaluated for each department,
using <literal>d</literal> as an alias to the department object. The
result of this expression will be a list of String values.
</para>
<para>
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:
</para>
<programlisting>#{company.departments.{d|d.size()}}</programlisting>
<para>
Projections can be nested. The following expression returns the last
names of every employee in every department:
</para>
<programlisting>#{company.departments.{d|d.employees.{emp|emp.lastName}}}</programlisting>
<para>
Nested projections can be slightly tricky, however. The following
expression looks like it returns a list of all the employees in all the
departments:
</para>
<programlisting>#{company.departments.{d|d.employees}}</programlisting>
<para>
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:
</para>
<programlisting>#{company.departments.{d|d.employees.{e|e}}}</programlisting>
<para>
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.
</para>
</section>
</chapter>