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