On Mar 27, 2:13 pm, Daniel <[EMAIL PROTECTED]> wrote:
> Hi all,
>
> I have a source code generator, portions of which works off JSP-like
> templates. I used Java as template language (convert template to Java
> source code, compile it, load class, provide user with a wrapper) for
> quite a long time, now there is a desire to switch to JavaScript to
> make templates easier to read, so we considered Rhino.
>
> I am trying to do this:
>
> Step 1) User creates a Java class that handles all logic:
>     public class Template extends
> some.fairly.complex.java.backend.BaseJavaClass
>     {
>         public String getName();
>         public abstract void generate( java.io.Writer out );
>     }
>
> Step 2) User creates a template, which produces the source code :
>     Hello <%getName()%>
>
> Step 3) My framework translates the template from step #2 into the
> following JavaScript code:
>     var p = Packages.some.fairly.complex.java.backend;
>     var result = new JavaAdapter( BaseJavaClass, {
>         generate: function (out) {
>            with (this){out.write("Hello,"); out.write(getName());} }
>     });
>
> Step 4) Template is used as follows:
>     Template template = TemplateFactory.getTemplate( Template.class );
>     template.setName("Dan");
>     template.generate( writer );
>
> The getTemplate(...) simply takes care of loading the template from
> resource, converting it to JavaScript code, retrieving the result
> variable as JavaNativeObject and unwrapping it.
>
> Pure Rhino worked just fine. The Rhino contribution included with Java
> as part of JSR-232 has Sun's version of JavaAdapter, which will only
> accept interfaces as first argument, so the central trick of the game
> did not work (BaseJavaClass contains some valuable logic and cannot be
> made into an interface).
>
> The major functionality is in that
> some.fairly.complex.java.backend.BaseJavaClass so I cannot really move
> it into JavaScript, it must remain in Java. At the same time the
> template is using some methods of the Java class, so it cannot really
> be independent from Java. I figured out a hack around this limitation
> by replacing step #3 with:
>
>     var result = {
>         generate: function (out,thiz) {
>             with (thiz) { out.write("Hello,");
> out.write(getName()); }
>         }
>     };
>
> and replacing step #4 to do something like this:
>    TemplateGenerator generator =
> TemplateFactory.getTemplateGenerator( Template.class );
>    Template template = new Template();
>    template.setName("Dan");
>    generator.generate( writer, template );
>
> It looks less sexy than original one, but is somewhat acceptable.
> Pros: you can now use template with different objects as long as they
> support certain interface.
> Cons: you have more code to write and additional logic piece
> (TemplateGenerator) to introduce.
>
> Alternative to this hack is to stick around Rhino implementation and
> don't bother with Sun's version.
>
> Question #1: Do you guys consider getting rid of JavaAdapter and
> switching to Sun's "limited" version or is it still safe to use it?

It's still safe. We don't have plans to switch to Sun's more limited
version. I believe the rationale for Sun's using the more limited
approach is that they don't include the JavaScript-to-Java-bytecode
compiler part of Rhino, and so could only use Proxys.

>
> Question #2: Is there a way to force Sun's version to accept classes
> in first argument (like custom JavaAdapter, maybe)?

I expect not given the underlying implementation depends on Proxy.

>
> Thank you very much in advance,
> Dan

FWIW, a more traditional approach to what you're doing is to expose
some.fairly.complex.java.backend.BaseJavaClass object into the Rhino
scope and just call it directly. If it's important to have each method
of some.fairly.complex.java.backend.BaseJavaClass appear as a function
rather than as a method of a global object, you can write static
methods in Java that you expose as functions in the Rhino scope. Those
methods can extract the some.fairly.complex.java.backend.BaseJavaClass
object from the global object using ScriptableObject.associateValue/
getAssociatedValue and call the appropriate method.

--N
_______________________________________________
dev-tech-js-engine-rhino mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-rhino

Reply via email to