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



Reply via email to