Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test EL expressions correctness statically?

Tags:

testing

jsf

el

On our web-application, we did some refactoring on the Java beans, and due to this refactoring, some actions / getters are not available anymore. For example, in the following example:

public class MyBean implements Serializable {

    // Old name
    // public String getFoo() { return "foo"; }

    // New name
    public String getBar() { return "bar"; }

}

If my JSF code still looks like:

<h:inputText value="#{myBean.foo}" .../>

then it will generate an exception.

My main concern is that some of the EL expressions may now point to unexisting methods on the Java bean, and I am only able to see that when I browse the adequate page. It becomes harder when the EL expression is located in a part that is rendered on specific conditions and / or rerender by Ajax.

So my question is how can I check statically the correctness of these EL expressions?

I've checked the JSFUnit tool as it provides such utility. So I tried this example, but it doesn't seem to work as expected. On a simple test page, with few EL expressions (some correct, some others wrong with unexisting beans and / or methods), the test succeed, which is not correct.

A really important note: My beans are defined in my Spring configuration, and not in the faces-config.xml.

Also note that I just need to check if the EL expression refers to an existing bean and method, and not necessarily that this action will be executed correctly...

Technical information:

Java 1.6, Spring 2.5, JSF 1.2, EL Functor, Facelets and Richfaces 3.3

like image 841
Romain Linsolas Avatar asked Oct 14 '10 14:10

Romain Linsolas


1 Answers

I didn't find a tool that matches my requirements. So I wrote a small bean on my application. This bean will provide an action that will read a directory and analyzes each .xhtml file in it (and do this recursively). Of course, I will have to run my application (so the analysis is not really static), but the advantage of this solution is that I will have access to the ELContext and ELExpressionFactory I really use in my web-application, both linked to my Spring context.

Here is interesting part of the code:

// Analyse a XHTML file
private void analyzeXHTMLFile(File f) throws IOException {
    List<String> lines = FileUtils.readLines(f);
    for (String l : lines) {
        List<String> els = getEL(l);
        for (String el : els) {
            evaluateEL(el);
        }
    }
}

// Get a List of EL on the line.
private List<String> getEL(String line) {
    List<String> el = new ArrayList<String>();
    int i = line.indexOf("#{");
    if (i == -1) {
        return el;
    }
    while (i != -1) {
        int j = line.indexOf("}", i);
        if (j == -1) {
            return el;
        }
        el.add(line.substring(i, j + 1));
        i = line.indexOf("#{", i + 1);
    }
    return el;
}

// Evaluate the EL
private void evaluateEL(String el) {
    FacesContext context = FacesContext.getCurrentInstance();
    ELContext elContext = context.getELContext();
    ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(elContext, el, Object.class);
    if (ve != null) {
        Object o = null;
        try {
            o = ve.getValue(elContext);
        } catch (PropertyNotFoundException pnfe) {
            // Handle this error
        }
        if (o == null) {
            // Handle another error
        }
    }
}
like image 88
Romain Linsolas Avatar answered Nov 10 '22 06:11

Romain Linsolas