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