Friday, April 18, 2014

JSF 2.2 Tip of the Day: Naughty Expression Language (EL)

Unexpected Effects

Many of you may know this already, but I was reminded the other day how this can catch even some of the most brilliant JSF developers. When you comment out a component in your xhtml page that has EL bindings, you may not be REALLY disabling it.
Expression Language (EL) is parsed and evaluated as the page is being rendered. As a result, any exposed EL syntax will be processed including functions which could have deleterious effects. For example, take a look at the following code, and guess what it will do.
1
2
3
4
<!-- #{indexBean.doSomething()} -->
<!-- #{indexBean.doSomething} -->
<!-- <h:commandButton action="#{indexBean.doSomethingElse()}" value="Submit"/> -->
<!-- <h:commandButton action="#{indexBean.doSomethingElse}" value="Submit"/> -->

So what happens?

Scary things happen....
  1. It executes
  2. Parser exception. The parser will try to find a property called doSomething
  3. It will execute, please note that there is no <h:form/>. It is not required since we are evaluating the EL.
  4. Parser exception. The parser will try to find a property called doSomethingElse

Sensei what do I do?

You have a couple of options. The first option is the easiest, and it is likely what you want anyway with your JSF pages. You can disable the comments. No need to transmit your development comments to the end users anyway. The second option is to add a - between the # and the { like this #-{indexBean.doSomethingElse()}.
The first option is handled by adding a configuration parameter to the web.xmlfile as shown below.
1
2
3
4
<context-param>
    <param-name>facelets.SKIP_COMMENTS</param-name>
    <param-value>true</param-value>
</context-param>
Here is a more complete example:
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
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Naughty EL</title>
    </h:head>
    <h:body>
        <h1>
Naughty EL</h1>
<p>
            Expression Language (EL) is parsed and evaluated as the
        </p>
<p>
<strong>Note:</strong> You can disable the comments including the EL which may not be disabled by using the following
            configuration parameter in the <strong>web.xml</strong>.
        </p>
<pre>
            <context-param>
                <param-name>facelets.SKIP_COMMENTS</param-name>
                <param-value>true</param-value>
            </context-param>
        </pre>
<p>
If you want to see the EL and its associated issues, please look at the source code and comments</p>
<!-- This example will execute because the EL ends with () -->
        <!-- #{indexBean.doSomething()} -->
        <!-- The result is the following -->
        <p>
Did the EL execute: <h:outputText value="#{indexBean.message}"/></p>
<!-- This example will not execute, but will result in a parse error because their is no property called doSomething -->
        <!-- You would need to remove the - from between # and { -->
        <!--#-{indexBean.doSomething}-->
 
        <!-- Oh, so you thought you disabled the component didn't you? Guess what? It is also not in a h:form ...-->
        <!--<h:commandButton action="#{indexBean.doSomethingElse()}" value="Submit"/>-->
        <!-- The result will be displayed in the messages below -->
        <h:messages globalOnly="true"  style="color:red; font-size: 32px;"/>
        <!-- <h:commandButton action="#-{indexBean.doSomethingElse}" value="Submit"/> -->
    </h:body>
</html>
The result of the code is as follows:

The complete code example was developed using NetBeans 8.0 and GlassFish 4.0 on JDK 8. The code can be found here: auto-execute-el

0 comments :

Popular Posts