Hi.

For me, EL-like languages always missed some functionality. Calling methods with parameters or simply doing things "above average" were always a pain.

As an experiment, I've tried to replace JSF EL (like #{mybean.myAccessor}) with JavaScript. At least to achieve the possibility to perform parameterizable method calls. So far it succeeded. Appeared to be easier than I thought.

I basically replaced ApplicationImpl with my own implementation, redefining createMethodBinding method to use Rhino JS implementation.
The core of the method is compilation of the passed reference:

String trimmedReference = reference.trim();
if (trimmedReference.startsWith(PREFIX) && trimmedReference.endsWith(SUFFIX)) {

final String scriptString = trimmedReference.substring(3, trimmedReference.length() - 2);

final Context context = Context.enter();
final Script script = context.compileString(scriptString, "", 0, null);

And creation of the method binding:


return new net.orless.hijack.editor.faces.binding.MethodBinding() {

//...
        public Object invoke(FacesContext facesContext, Object[] aobj)
            throws EvaluationException,
            MethodNotFoundException {

          Context context = Context.enter();
          try {
            ScriptableObject topScope = context.initStandardObjects();
Scriptable s = new ScriptableFacesContext(facesContext, topScope);
            final Object result = script.exec(context, s);
            if (result instanceof Wrapper)
              return ((Wrapper) result).unwrap();
            else
              return result;
          }
          catch (Exception ex) {
            throw new EvaluationException(ex);
          }
          finally {
            Context.exit();
          }
        }

      };

    }
    else {
      return super.createMethodBinding(reference, params);
    }
  }


ScriptableFacesContext is trivial:

public class ScriptableFacesContext extends ScriptableObject{

  private final FacesContext facesContext;

public ScriptableFacesContext(FacesContext facesContext, Scriptable scope) {
    super(scope, null);
    this.facesContext = facesContext;
  }

  public String getClassName() {
    return ScriptableFacesContext.class.getName();
  }

  public Object get(String name, Scriptable start) {
return facesContext.getApplication().getVariableResolver().resolveVariable(facesContext, name);
  }
}

Now , #{[....]} value bindings are compiled as JavaScript and then evaluated within the FacesContext context, using variable resolvers and so on.

A small example. In the tree I have command link like:

<h:commandLink immediate="true" action="#{[node.doIt('b')]}">
<h:outputText value="#{node.description}" styleClass="nodeFolder"/>
</h:commandLink>

The tree node class has a method:

  public String doIt(Object node)
  {
    System.out.println(node);
    return "";
  }

When I click on the node link within the tree, the node is printed to the system out:

[EMAIL PROTECTED]

Is anyone interested? I could share/contribute my sources. And would also be greateful for an advice from someone a bit more experienced with Rhino than I am.

ps. What is the easiest way to switch the used "Application" class? Apart from implementing and registering my own application factory.

pps. JavaScript is probably also interesting for value bindings.

ppps. Bindings could be easily implemented as Serializable/StateHolders. For instance, transient script + script string, script string is re-compiled by demand (when script is null).

Bye.
/lexi

Reply via email to