You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Sylvain Wallez <sy...@apache.org> on 2004/12/03 12:40:49 UTC
What do we need taglibs for?
Lots of emotions related to templating and/or taglibs lately, and the
feeling that both camps aren't that far from actually saying the same
thing...
So, why do we need taglibs for? Let's consider two examples that led me
to write JX macros, which are nothing but taglibs. One is in Cocoon,
it's the CForms template language, the other one is on a project, used
to render the path of a node in a tree.
First use case, CForms' jx-macros.xml:
We have the FormsTransformer, so why would we need forms template be
handled in the generator? The answer is simple: the template structure
can depend on the form contents.
Sure, the flow gives the form object to the view, so we could use the
basic JX control structures to do all the job. But macros gives the
template writer a higher level of abstraction, meaning he can directly
use widgets and their names rather than going through the widget tree
traversal API (which *is* code).
These macros also populate some template variables (e.g. "widget",
"repeater") that can be used for pure-JX control structures (e.g.
testing that a repeater is empty, that some section is visible, etc),
making life easier for the template writer and standardizing
form-related variable names.
Second use case, displaying a node's path:
I worked on a project where we had to display lots of nodes in a tree in
a way similar to e.g. dmoz.org categories [1], using their path. Should
we iterate backwards a node's ancestor tree to display its full path in
each and every location where a node has to be displayed? Nah, I wrote a
simple macro, which allowed me to write:
<topic:path node="${mynode}"/>
for "passive" display and
<topic:linked-path node="${mynode}"/>
to have each node in the path holding an hypertext link.
In this case, the macro/taglib is actually a formatter.
Now the ESQL case:
The main question is "where should the query be written"? I agree that
writing SQL statement in the template is ugly and mixes concerns (even
if very powerful when you master this gun). That's a business-logic
concern and should therefore be written in some kind of controller.
But the main question that led people to fight around ESQL seems to me
related more to the actual place (and time) where the query should be
executed, people arguing that if the query is written in the controller,
we loose some control in the template, and on the other side that if the
query is executed in the template, we mix concerns.
But why should the query be executed at the place where the SQL
statement is written? Without throwing in the big Hibernate, simpler
systems such as Brian McCallister's jDBI [2] and iBatis [3] allow to
have named and parameterized queries where the SQL code is totally
separated from the place where the query is actually executed. We can
then have a controller of some kind (or simply a query repository)
prepare a statement given a name and parameter values, and then let the
template execute it when needed. Just as in Hibernate, lazy loading of
the result set.
Taglibs are to templates just what factorization in classes and methods
are to Java code. Taglib features could equally well be provided as
extension functions to the expression language, but writing them in XML
(either with tags or attributes) just seems more consistent with the XML
world of the view layer.
Sylvain
[1] http://search.dmoz.org/cgi-bin/search?search=xml
[2] http://kasparov.skife.org/jdbi/
[3] http://www.ibatis.com/
--
Sylvain Wallez Anyware Technologies
http://www.apache.org/~sylvain http://www.anyware-tech.com
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
Re: What do we need taglibs for?
Posted by Glen Ezkovich <gl...@hard-bop.com>.
Please excuse this rather lengthy post. I'm trying to make a simple
point. Why are we trying to cover all cases in a single generator? If
you have a generator that can be configured to use any and all taglibs
then you don't need any other generators. Just stick the appropriate
tags in a template and let it run. Create a taglib for files, one for
requests, one for java, one for python, one for ... etc. The list never
ends. I think the sound approach is do our best to keep concerns
separate. We can't prevent others from mixing concerns, but we can make
them at least have to expend some effort and thought before they do.
On Dec 3, 2004, at 5:40 AM, Sylvain Wallez wrote:
>
> Taglibs are to templates just what factorization in classes and
> methods are to Java code. Taglib features could equally well be
> provided as extension functions to the expression language, but
> writing them in XML (either with tags or attributes) just seems more
> consistent with the XML world of the view layer.
Ok, agreed. I have nothing against taglibs. I have no problem with
using them in the implementation of a JXTG replacement. What I disagree
with is having any and all taglibs as part of a single generator. I
think the macro approach to formating injected data is much better. It
allows things to be domain specific in ways that generally will not be
done by a generic library. I usually don't need to format all
ResultSets as a generic table. Formating product comparisons is
different then then displaying the 3 best selling products. I want to
be able to have a tag/macro that expands a product in the appropriate
way so I can inject it into a product-comparison element or a
best-sellers element.
I'm probably missing something in my understanding of what a generator
is supposed to do, since it seems that many want it to do everything.
The way I see it a generator should convert a data source to a stream
of sax events. This is where things start. If my data source is a
database, I need to get the required data and put it into the stream
appropriately. If my data source is a Java object/s I need to extract
the properties I need and inject them into the stream. At this point
all I want is to produce a sax stream from the data. The resulting
output should be the same if my data source was an XML file, a database
or whatever. If I serialized immediately after generation I should be
able to get a valid xml document that contains data only and no view
information. All I should have done is extracted data from the model.
Template generators should inject that data into a user defined
template.
Now, an example that has been brought up before is that of pretty
printing a date. Should this be handled by the generator? I think not.
If the generator were to have a tag for a date, I believe it should not
be concerned with formatting the date for the view. Rather, it should
be concerned with injecting the date into the stream as data. It should
take the date, whether from a database or a Java Date, and inject it
in to the sax stream as something like
<date>
<year>2002</year>
<month>2</month>
<day>23</day>
<time>
<hour>12</hour>
<minutes>30</minuets>
<seconds>12</seconds>
</time>
</date>
Should this even be a tag backed by a Java class? I'm thinking a macro
works fine. This requires no complex computations, just the extraction
of data. Formating should be left to a transformer.
The problem as I see it is that by creating a taglib plug-able
generator, you are inviting easy misuse. I don't see many use cases for
mixing data from multiple types of data sources (such as concatenating
"xyz" from an XML file and "abc" from a result set) so the idea of
having generator that can deal with tags from different data type
access libraries doesn't make a lot of sense. (If I did have such a
use case I'm pretty sure I wouldn't want to handle it in a geneartor)
On the other hand as I said in a previous post, the approach of having
a taglib plug-able architecture is sound. If someone wants a single
generator that can do everything just like XSP, then fine let them
write one. But make them write one. Make them expend the minimal effort
of extending an abstract TemplateGenerator and configuring it to work
with their required taglibs. Once the taglibs exist, it would take
about 5 minutes to get it working. I just think that having each
generator do one thing and do it well is a much sounder way to proceed
then having everything in one.
I think it makes more sense to have unlimited plug-able rendering
libraries for a transformer. This is where data should be formated and
the view rendered. Sure people could abuse it, but that is their
problem. If you want to render a calendar do it with data from the
generator, render it in with a transformer. If this turns out to be a
big performance hit for you, you may need to create your own custom
generator. (Or a more efficient transformer)
On the other hand XSL extensions might be all you need to handle any
formating.
I think with flow, we sometimes forget that the pipeline is the
original controller. That is where we separate concerns. It is my hope
that we do not encourage the creation of generators that render the
view. Seven or so months ago when I first started working with cocoon,
it was view rendering using JXTG that bit me. As the visual design of
the site developed there were many templates that needed to be
modified. Now we only convert objects to xml. All rendering is handled
by the XSLT Transformer and a few style sheets. It is much easier to
maintain.
I understand that situations will dictate that performance is king and
the option to quickly put together a generator that can do everything
at once is very attractive. Both in terms of performance and
development time. In those situations just do it. Just don't make that
the standard way of doing things.
Thanks for listening.
Glen Ezkovich
HardBop Consulting
glen at hard-bop.com
http://www.hard-bop.com
A Proverb for Paranoids:
"If they can get you asking the wrong questions, they don't have to
worry about answers."
- Thomas Pynchon Gravity's Rainbow
Re: What do we need taglibs for?
Posted by Peter Hunsberger <pe...@gmail.com>.
On Fri, 03 Dec 2004 12:40:49 +0100, Sylvain Wallez <sy...@apache.org> wrote:
<snip> lots of discussion on taglibs and templates</snips>
> Taglibs are to templates just what factorization in classes and methods
> are to Java code. Taglib features could equally well be provided as
> extension functions to the expression language, but writing them in XML
> (either with tags or attributes) just seems more consistent with the XML
> world of the view layer.
There is another way. It's sort of weird and in it's simplest
implementation requires modern browsers but you previously asked how
our templating system works, so I might as well fill you in on how we
handle things like this.
First we separate the concept of "screens" (or pages) from templates,
there can be multiple templates per screen. Each template has a base
type, the two most important for this discussion being "edit" and
"grid". A edit template allows random positioning of individual
objects anywhere on the screen using relative positioning and XSLT
ordering of the objects (to make the CSS calculation of the relative
positioning easier). A grid produces a regular table.
Either of these layouts can contain the other. We use iframes to embed
any given template within another. This couples a single URI to any
given template. We have a special form of object known as a "key" that
is used for managing relationships between collections of data and
when you embed a template within another any key values from the first
are automatically passed to the second as request parameters on the
iframe src. Thus, mapping one to may relationships in the database
has an exact equivalent at screen creation time and you don't end up
denormalizing in you query and then splitting things back apart at
presentation time.
There is a requirement to make sure that the appropriate screen types
are mapped to the correct data producers on the back end. We have
logic that automatically selects between screen types if multiple
matches are defined, but if all you have is a "edit" screen and the
keys you get passed from your container result in multiple rows being
produced you will see only a single edit screen (though I guess we
could automatically produce the corresponding grid in this case).
I said at the beginning that the simplest implementation requires
appropriate browser support, that being iframes. However, you could
manage this all on the back end, doing essentially server side
embedding of the templates within each other and still mapping the
population of each portion to the proper URI. From what I've read I
don't think the result would be much more complex than some of cforms
(or the existing templating proposals for that matter)...
IOW, if you need to refactor templates, allow templates to be
normalized WRT to each other. I don't think you need a new concept....
--
Peter Hunsberger