The standard JSP2.1 EL includes support for resolving the following:
- Java language arrays and
java.util.List
objects by numeric index
-
java.util.Map
objects by map key
-
java.util.ResourceBundle
objects by property key
- Bean Properties by property name (but only if the object is not a
Map
,
List
or ResourceBundle
)
There is no built-in support for method access. The standard function
support in the unified EL is through pluggable FunctionMappers that map
expressions like ${prefix:fnName(a,b,c)}
to static methods.
The actual mapping can occur through a JSP2.1 taglib, or by providing a
custom javax.el.FunctionMapper
implementation.
Now assume you want to do something fairly simple like obtaining the
lower case version of an existing string. You can't just write item.name.toLowerCase()
like you would in java code. Instead you have to define a library class
with a static method, like:
package mystuff;
public class MyStringUtils
{
public static String toLowerCase(String value)
{
return value.toLowerCase();
}
}
Then add a reference to this function within a tag lib, like this:
<function>
<name>toLowerCase</name>
<function-class>mystuff.MyStringUtils</function-class>
<function-signature>
java.lang.String toLowerCase( java.lang.String )
</function-signature>
</function>
Then you can invoke it within a JSP/JSF page like ${f:toLowerCase(item.name)}
where f
is the prefix you have mapped the tag library to. [Actually, in this
particular case the JSTL implementation does provide just such a taglib function
-- fn:toLowerCase(), but the argument still applies, since the provided functions are still
quite limited.]
A few issues with this approach are:
- You have to write a utility function and a tag library entry for
every method you need to access (or you could write an invokeZeroParamObjectMethod
type function that uses reflection. Invoking it would look like
${f:invokeZeroParamObjectMethod(item.name,
toLowerCase)}
. You would still need multiple versions for the
different number of arguments that are possible).
- The syntax is slightly awkward.
- More significantly, you can't use it in places like the
faces-config.xml
managed bean initialization (which is one place that really needs it).
You could get around this by defining your own FunctionMapper library
that is installed with a ServletContextListener
referred
to in the web.xml
descriptor. However the effort to do all
that is almost the same as the effort to create this EL Functors
resolver library.
To do the same thing with the EL-Functors library, you need to add
the library to your project (as described below), and then use an
expression like ${item.name.toLowerCase$}
.