Well, you pretty much listed all pros and cons yourself. JavaScript is
a general-purpose programming language, and while quite malleable,
you'd still likely end up with a lot of syntactic cruft in your
"templates" (that is, programs whose main purpose is to render textual
output). You might have better luck by programmatically constructing
a DOM and having it rendered, maybe with some library that makes
constructing a DOM expressive.
That is, for this particular purpose (rendering textual output)
FreeMarker is likely more ergonomic than JavaScript, because it was
expressly designed for exactly that purpose. That is not to say that
if you apply yourself to the problem and write a JS library with the
goal of making text output generating in JS as ergonomic as possible,
you couldn't arrive at something nice. I'm sure you could. Question
is, do you want to / have the resources to do it.
That said, I don't see any showstoppers. I'd be curious to hear about
your results if you decide to go with Rhino.
Attila.
On 2009.09.14., at 3:28, DVD wrote:
Hello
, Is there a comparision for pro and cons to use freemarker versus
rhino (with a template unitility class)
as general purpose template engine?
rhino is quite matured but I have seen few apps/webapps are using
it as template engine.
I have been using Freemarker but feel that using Rhino is much
cleaner and compact, of course,
only need to use Javascript in web dev instead of the extra
freemarker mini language.
But I wonder if there have been showstoppers, performance issue when
comparing these two choices.
Thanks
Attila Szegedi wrote:
Okay, there are several differences in the design of the two
languages that make it more difficult for Rhino to work that way:
1. FreeMarker language is designed so that the execution of the
template can't mutate the data you passed in. A template can define
new variables that are local to an individual "process()" call, but
it completely lacks language elements that would modify the passed-
in ones (redefining existing names will simply result in a new
local that "shadows" the original; much like JavaScript does with a
prototype scope + a top level thread local scope). JavaScript,
being a generic imperative programming language, doesn't live with
this constraint per se. Best you can do to lower the overhead is
the use-shared-global-scope-as-prototype approach that both Martin
Blom and I mentioned, although as we both said, it breaks the
isolation of programs from one another, but again, it shouldn't be
much of a problem if your scripts don't actually go rogue on those
shared objects.
2. FreeMarker's runtime execution model does define a program
loading and caching mechanism, JavaScript doesn't have one, by
design. In JavaScript, it's up to the host environment to provide
program loading. Behind FreeMarker's "getTemplate()" call (and its
[#include] directive) there's a whole loading, compiling, and
memory-sensitive caching mechanism. Again, in JavaScript, and
consequently Rhino, there is no such thing. You can get something
similar by using existing web frameworks that support Rhino, or
roll your own. However, in basic case, just using
Context.compileReader() and then repeatedly calling exec() on the
resulting Script object is all you need.
Lots of people use the shared global scope + precompiled scripts
with Rhino and are quite happy with the performance. If you
implement these measures, there's good chance you'll be happy too;
if not, you'll have to profile your system, identify actual
bottlenecks, and then please come back to us and we'll see what we
can do. But first try shared global scope + precompiled scripts.
Hope that helps.
Attila.
--
home: http://www.szegedi.org
twitter: http://twitter.com/szegedi
weblog: http://constc.blogspot.com
On 2009.08.31., at 1:13, DVD wrote:
Hi, there. I have been using freemarker :-). I'd like to
clarify if I could do the similar way to that of freemarker
in freemarker, I could do during program init (main thread)
class Main{
static Configuration cfg = new Configuration();
static cfg.setDirectoryForTemplateLoading(new File("dir"));
static Template temp = cfg.getTemplate("test.ftl");
}
then in any other methods (whatever thread it could be) just do
Map root = .... (fillup data model)
Main.temp.process(root,....)
I have not seen an example for rhino to do this way. The template
would only do normal template processing.
no fancy stuff. Can Rhino have a mode to do this way with thread
safety gurranteed.
Thanks very much.
Attila Szegedi wrote:
What other template engines work this way? (I'm one of primary
developers of FreeMarker, and the concept doesn't strike me as
familiar there :-) )
Anyway, this too is possible. In one context (say, the one that
also compiles the script, although this is not strictly necessary):
globalScope = cx.initStandardObjects();
then in the repeated contexts (i.e. those handling HTTP
requests), just do:
ScriptablelocalScope = cx.newObject(globalScope);
localScope.setPrototype(globalScope);
although you will likely also need to create the contexts through
a context factory that returns true for
hasFeature(FEATURE_DYNAMIC_SCOPE) if you do that. Anyway, you can
try without that actually, but if you run into weird behaviour
with properties missing in the global scope. Also, be aware that
now the global scope became shared mutable state between threads.
If your JS scripts are good citizens, and don't do fancy stuff
like redefine the Array constructor or such (that is, treat the
stuff in global scope as immutable) then you'll be fine.
Attila.
On 2009.08.30., at 16:11, DVD wrote:
What I would expect is Rhinoe would have a mode that allows the
following
(it is ok to disable some features such as concurrentcy within
JS to make it happen)
public static context = Context.enter(); public static
globalCompiledScript = context.compile(script)
public static globalScope = .....
(the above is done in main thread , not threadlocal, just done
once during program init)
then in each thread,
localScope = ..... (localscope backdropped by globalscope)
globalCompiledScript .exec(localscope)
Most other template engines work this way. would it be possible
for Rhino?
Martin Blom wrote:
DVD wrote:
Thanks. I have many threads come and go instead of a fixed
pool so
the overhead is big.
I hope rhino to have a mode that would allow a preloaded/
compiled JS
(template) to be executed repeatedly
with different scope (essentially a template engine ) to
produce an
output string.
the template would run in only single thread before producing
the output.
Equivalent of Freemarker engine. Would it be possible? Or
because of
this issue,
Rhino has not been widely used as template engine for Java,
compared
to others like
velocity/freemarker.
This should definitely not be a problem.
In ESXX, for instance, I have an ExecutorService with a
ThreadFactory
that enters/leaves a JS context as part of the thead's
lifespan. These
threads then handles requests by calling functions in a JS
application
scope. The application scope is set up once when the JS app is
loaded,
by executing the pre-compiled JS scripts files (using
Context.compileString()) with it.
If you want your requests to execute isolated from each other,
you can
simply create a new global scope and execute the compiled
script with it
for each request.
(It's also possible to mix these strategies by having a shared
top-level
scope and using the prototype chain to add per-request scopes
(needs
Context.FEATURE_DYNAMIC_SCOPE, I think), but I could never
quite get
this to work properly, since in ESXX, I need to allow arbitrary
Java
threads to call JS functions, and there were some issues that I
have
forgotten about now.)
_______________________________________________
dev-tech-js-engine-rhino mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-rhino
_______________________________________________
dev-tech-js-engine-rhino mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-rhino