Simon Kitching schrieb:
Werner Punz schrieb:
Andrew Robinson schrieb:
Think I worded this too strongly, as renderers also produce HTML via
Java. I just think that if you are going to have templates, it would
be great to keep them in separate files, be it *.vm for velocity or
xhtml/xml for facelets/JSF2 or what have you. These files can not only
be edited by some tools (at least facelets can, not so sure about
velocity), but they can also be changed on the fly without any java
recompilation. Java went away from servlets building HTML for this
reason and adopted JSP. I personally do not feel that going back to
more Java built HTML is going to be a great direction, but maybe that
is just me.
Actually I am not harsh about myfaces not adopting my solution,
it was just an effort to improve readability on the source from my side.
No harm is done if we do not adopt it.
Problem is as I see it, everything is better for jsf 1.x than the
current printwriter API.
Even my, and I agree from an academic standpoint dirty, solution.
If anyone could provide a decent backport of the JSF2 templating
compiler to JSF1 I would be happy as well.
(My compiler building knowledge is way too limited to pull this off in
a limited time myself)
But the problem persists, how are we going to improve the readability
of the rendered code and how do we maintain the much needed speed on
component level?
We are not talking about doing away with any existing templates, right?
AIUI we're just talking about replacing a whole bunch of calls to
responseWriter.startElement("span")
responseWriter.write("hello," + planetName);
responseWriter.endElement("span")
etc
with some kind of in-class templating that compiles down to exactly the
same code, but has a more readable syntax. The performance will clearly
be exactly the same as the current code, because it results in exactly
the same code in the end. Whether it is actually easier to work with is
up for debate, but I've spent hours looking at code for the Calendar
control trying to figure out exactly what it generates; all those
StringBuffer manipulations are really nasty. The current approach sucks
for readability.
So Werner's proposal is not terribly radical (though clever). It's
equivalent to SQLJ, but compiles direct to bytecode rather than java
source.
Refactoring all the components to use external templating interpreted at
runtime is certainly more flexible and elegant but Werner seems to have
proved that this is just a no-go from the performance point of view.
Pages do often have dozens of components, and rendering dozens of
Velocity templates doesn't seem to be feasable. Any template-based
approach would have to be one with very high performance.
JSP2.0 does support "tag files", ie jsp files with suffix ".tag" that
can then be referenced via jsp tags in a page. I would presume that
these do get precompiled like other jsp files do, but cannot see how we
could hook into that. Same with Facelets; I don't know of a way to have
a template processed into an optimised form that the renderer can pass
data to; facelets pages are used at build-time to create a view-tree,
not at render time when the view-tree is being walked to generate output.
I suppose that Werner's templating approach could be applied to
*external* templates rather than ones embedded in the class.
For example, a "HtmlCalendar.tmpl" file could exist next to the .java
file, and could generate a HtmlCalendarTmpl.class file at compiletime
with a static render(Map args) method and a bunch of print statements.
This could then be invoked from the calendar component. That does feel
cleaner to me than embedding the template within the java code, although
the end result is pretty much the same. This then *is* effectively a
high-performance template system, although a recompile is required to
change the template output. What do you think, Werner?
I don't think comparing this to JSP vs hard-coded HTML is fair. Pages
are expected to be changed on a daily basis; the representation a JSF
component generates will often not change between releases (ie remains
untouched for months).
One thing I did try a while ago was to simply define a template string
in the java class, then use java.text.MessageFormat.format(template,
args). But I don't think that the performance is really good enough.
Regards,
Simon
Actually two clarifications,
the first one is I compile to java source not bytecode, it was way
easier to do that, and makes debugging easier afterwards!
I thought about going to external templates, but then went against it.
First of all I wanted to have the code in place because if you look at a
component about 80% is infrastructural code 20% maybe the pure
rendering. But the printwriter api, makes those 20%, 50% of the
resulting codebase, and decreases the readability!
The second issue was simply, that going towards exernal templates means
following
a) You have to use lookup maps for the variables, which I could avoid by
simple doing a rewriting engine.
b) You either have to give the compiler type information to do the
typecasting, or you have to generate introspection code.
I will give an example:
$myVar.helloString
can be expanded into myVar.getHelloString() which is exactly what you
would do in handwritten code.
however if you use param maps then you run into following:
you have to do introspection whether the passed variable has a property
myVar or you additionally have to give the templating compiler the info
of the type of myVar so that internally can do the casting in the
generated code alike
MyVarType _generated_MyVar = (MyVarType) variablesMap.get("myVar");
_generated_MyVar.getHelloString();
The myVarType must be looked up upfront by the compiler in a type map,
probably in the template itself, hence you add the entire variable
declaration into the template!
To avoid introspection I probably would go the second approach, though,
but that still means you have to do a map lookup vor every variable in
the template and you have to add the runtime type information into the
templating code call!
Note you still can introduce a mvc pattern with the plain rewriter by
simply pushing all the templating code in their own classes and pass the
parameters as parameter lists down the methods.
This basically would result in the same but without manual the runtime
type information addition!
Werner