JSF 1.2 to JSF 2.2 Migration - MethodBinding in Custom Component

406 views Asked by At

I've recently inherited a legacy (JSF 1.2) project and have been tasked with making it JSF 2.2 compliant. I'm not an experienced JSF developer, and have been following various advice from around the web. One problem that I'm faced with that I cannot find an adequate solution to is passing method bindings to custom components through expression language parameters. Here is an example:

browse.xhtml:

<?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">

<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:custom="http://www.custom.com/jsf/custom">

<f:view>
    <head>
    <title>Title</title>
    </head>
    <body>
        <custom:condition test="#{MyBean.canView}">
            Some private data here
        </custom:condition>
    </body>
</f:view>
</html>

MyBean.java:

public class MyBean {
    public String canView() { return "true"; }
}

Conditional.java (mapped to custom:condition tag):

public class Conditional extends UIComponentBase {

    <snip>

    private MethodBinding testBinding;

    public MethodBinding getTest() {
        return testBinding;
    }

    public void setTest(MethodBinding test) {
        testBinding = test;
    }

    public boolean test(FacesContext context) {
        boolean ret = true;
        if (testBinding != null) {
            try {
                Object o = testBinding.invoke(context, null);
                ret = o != null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    <snip>

}

I've gotten some basic code working by passing a String expression such as "MyBean.canView" leaving the EL hash/curly brackets off, then, concatenating them back on in the component and creating and invoking a MethodExpression. That all seems a bit of a hack, not to mention to doesn't accomplish the EL expression evaluation in the facelet, like the previous JSF 1.2 code did.

Am I missing something? How should this JSF 1.2 code be upconverted to JSF 2.2?

EDIT: Here is my "hack" that kinda, sorta works. Hoping there is a better way.

public class Conditional extends UIComponentBase {

    <snip>

    public boolean test(FacesContext context) {
        if (testBinding != null) {
            Object ret = null;
            try {
                ApplicationFactory factory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);      
                MethodExpression methodExpression = factory.getApplication().getExpressionFactory().createMethodExpression(
                FacesContext.getCurrentInstance().getELContext(), 
                    "#{" + testBinding + "}", Boolean.class, new Class[] {});
                ret =   methodExpression.invoke(FacesContext.getCurrentInstance().getELContext(), null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (ret == null) return false;
        }
        return true;
    }

    <snip>

}
0

There are 0 answers