You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by Santiago Gala <sg...@hisitech.com> on 2003/07/08 00:42:28 UTC

Re: Coupling of Turbine and Velocity codebases

Jonathan Revusky escribió:
> I finally broke down and looked at some of the Turbine code, because I 
> wanted to know what people were talking about.
> 
> I did a CVS checkout of the head, jakarta-turbine-2, which is where all 
> the commits seem to be going.
> 
> I then did a grep over the sources looking for the various points at 
> which classes in the org.apache.velocity.* hierarchy are referenced.
> 
> I found 21 (!) different source files which reference Velocity classes. 
> Now, there was again a reaction of irritation with this. Henning and a 
> couple of other people had proposed (with a certain aggressive subtext) 
> that there was some onus on *me* to submit a patch if I "wanted" the FM 
> support back.
> 

IMO, most of what is needed is to abstract the 
org.apache.velocity.context.Context class as a generic Template Context 
for the pull service and to substitute most "VelocityXXX" class names 
for "TemplateXXX"

Look for instance to the VelocityDirectLayout. It only uses the Context, 
and the main Velocity class to get it.

If the FM context for bean like object has a similar interface, it does 
not look like a daunting task.

[sgala@patusan jakarta-turbine-2]$ egrep -Rl "org.apache.velocity.[^c]" 
src/java/
src/java/org/apache/turbine/services/pull/TurbinePullService.java
src/java/org/apache/turbine/services/velocity/TurbineVelocityService.java

Now, this work will be much better done if someone who knows the needs 
or specific template engines helps in the abstraction process of the 
context.

Just my 2 (Euro) cents.


(...)

Regards
-- 
Santiago Gala
High Sierra Technology, S.L. (http://hisitech.com)
http://memojo.com?page=SantiagoGalaBlog



---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: Coupling of Turbine and Velocity codebases

Posted by Jonathan Revusky <jo...@revusky.com>.
Daniel Rall wrote:
> Jonathan Revusky <jo...@revusky.com> writes:

>> From my experience, I think you can basically say that any Context
>> object is a hashtable of some sort. So, it is probably feasible just
>> to use java.util.Map and, if necessary, convert the Map into the
>> concrete class when needed in the concrete implementation. The whole
>> thing looks quite trivial.
>>
>>// in Velocity-specific concrete class, approximately:
>>void processTemplate(Map someMap, String templateLocation, Writer out) {
>>    VelocityContext vc = new VelocityContext(someMap);
>>    Template t = Velocity.getTemplate(templateLocation);
>>    Velocity.mergeTemplate(templateLocation, vc, out);
>>}
>>
>>// in FreeMarker-specific concrete class, you just use the Map directly
>>// since the conversion from the Map object occurs transparently.
>>void processTemplate(Map someMap, String templateLocation, Writer out) {
>>    Template t = Configuration.getTemplate(templateLocation);
>>    t.process(someMap, out);
>>}
>>
>>I mean, the fundamental pattern of usage is just so similar that
>>abstracting it out and simply using whatever template engine from a
>>common API is really quite a trivial exercise.
> 
> 
> This apples to apples comparisons is a natural first step, and
> provides solid examples.  An apples to zucchini comparison is also
> helpful, since the use cases which don't fit a model are the ones
> which cause its users the most trouble.

Well, presumably you'd go through a preview or beta part of the release 
cycle, where such issues would have a chance to come up, and the API is 
not yet written in stone.

Actually, for example, I think that the API I gave above is lacking in 
one significant respect. It should take a Locale object as a parameter. 
Then the FreeMarker implementation would look like:

void processTemplate(Map someMap, String templateLocation, Writer out, 
Locale locale) {
     Template t = Configuration.getTemplate(templateLocation, locale);
     t.process(someMap, out);
}

Then the getTemplate() method used would be one that takes the locale as 
an argument. It also means that the template would have an associated 
locale, so that decimal numbers and time/date objects get transparently 
formatted by default locale conventions.

Of course, the extremely streamlined Velocity template engine has no 
such locale-awareness, so the locale argument would simply be ignored by 
the Velocity implementation and could perfectly well be null. However, 
note that, if Velocity development is resumed, and these kinds of i18n 
features are introduced, then having the extra locale param could be 
useful for the Velocity service as well. I mean, it is useful to 
anticipate things that could possibly be necessary at a future point, so 
that you don't paint yourselves into a corner.

In any case, I think that things like this would likely come up in a 
preview or beta cycle where things are more subject to change than a 
release candidate or stable release. And then you'd freeze the API when 
things got past the beta part of the cycle.

> 
> I ran through a few such comparisons, and a Map-based context handles
> all use cases for the input processing step (objects are simply
> gloried hashtables).  One doesn't always want to involve character
> encodings in content generation (e.g. for binary output), so using a
> generic Object interface for output is preferred to coupling the API
> to Writer.  This also handles output of more complex types (e.g. DOM
> trees, etc.).

 >
 > public interface ContentGenerationSystem
 > {
 >     /**
 >      * Performs content generation, converting its inputs to the
 >      * appropriate CGS-specific types.
 >      *
 >      * @param context Contextual information used as inputs to the
 >      * content generation system.  May be <code>null</code>.
 >      * @param target The target to generate content for.  May be
 >      * <code>null</code> if <code>context</code> contained sufficient 
state.
 >      * @param output Where to send the generated content.
 >      */
 >     void generateContent(Map context, String target, Object output);
 > }
 >
 >
 > If multiple output types are supported, generateContent() can use the
 > instanceof operator to choose the appropriate action.

Well, it depends what you think you're abstracting. To my way of 
thinking, a template engine is a system for generating text. You take a 
reusable template, and a data model, and from those two things, a 
procesing job generates a bunch of text. As such, to say that it pipes 
its output into a Writer seems reasonable to me. In general, I think 
you're better off using core Java API's, like java.util.Map and 
java.io.Writer, that java programmers are familiar with. It becomes 
quite clear immediately to people what is going on: a Map is an object 
that represents a set of key->value mappings and a Writer is an object 
through which you can pipe text. It also means that any custom Map or 
Writer implementations that people come up with should be usable in this 
spot.

Now, it is true that an XSLT transformation engine is not exactly a 
template engine. It actually transforms one tree into another tree, and 
the fact that the tree it creates can be output as text is sort of 
incidental. However, if you're abstracting away an XSLT transformation 
engine as if it's purely a text generation tool, i.e. treating it as a 
template engine, then you could perfectly well have it use the Writer. 
It simply outputs the serialized text version of the tree into the writer.

And of course, if you have a separate "tree transformation service" of 
which XSLT is kind of the archetype, then you could have a separate API 
and have your XSLT-related object implement that interface as well, so 
it's not as if you're really painting yourself into a corner by saying 
that a template engine service takes a Writer as an argument and shoves 
text through it.


> 
>>Now, there clearly is interest on the part of some users to be able to
>>try FM from Turbine. I've seen signs of that on this list and I have
>>some private email that bears this out. So my earlier offer still
>>stands: Get your house in order on this stuff, and I'll help you get
>>it working. But the ball is currently in your court on this.
> 
> 
> Personally, I'd be very happy to see FreeMarker available in Turbine
> again, so long as its integration is supported by an active developer.
> The original reason it was dropped was a lack of both developer
> support and user interest.

Well, frankly, when I look at the sheer scope of Turbine as a project, 
and compare that with the technical difficulty of keeping a 
FreeMarkerXXXService.java sort of code synched up with the latest 
FreeMarker, the latter seems quite trivial.

As for the lack of user interest, I have already stated (perhaps ad 
nauseam) that this is something of a contrived half-truth. Just given 
the fact that the last FreeMarker version "supported" was extremely 
obsolete, it is quite obvious that this would not elicit any end-suer 
interest. The only way you could say in a fair-minded good-faithed way 
whether there was significant end-user interest in FreeMarker or 
anything else would be if the current version were supported on an equal 
footing.

But look, if there is a clear API to implement with a clear contract, by 
which you plug a template engine into Turbine -- and if the rest of the 
framework uses that API and doesn't couple directly with Velocity 
classes -- i.e. if you have your house in order on this, I guess I would 
commit to keeping it working. It strikes me as a trivial enough task 
that I could commit to that.

But until you get things to that state, it's all rather hypothetical.

Regards,

Jonathan Revusky
--
lead developer, FreeMarker project, http://freemarker.org/

> 
> I'd be even more happy to see a light-weight content generation
> abstraction (something like what's outlined above), replacing what's
> in Turbine 3.





---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: Coupling of Turbine and Velocity codebases

Posted by Daniel Rall <dl...@finemaltcoding.com>.
Jonathan Revusky <jo...@revusky.com> writes:

> Daniel Rall wrote:
> > I'd like to point out the generic context implementation already
> > exists in the TemplateService in Fulcrum, and is used in Turbine 3
> > (and thus in Scarab).  I urge you not to give specifics of a generic
> > context path even a moment's consideration, as doing so adds needless
> > complexity and offers very little in return.
> > Any movement towards a generic context interface should use an opaque
> 
> > type, like Object or an empty marker interface (from what I saw of the
> > recent TorqueComponent impl., Avalon uses these to good effect).
> > Content rendering engines are inherently different, and pretending
> > that they are does not make them so (read: don't fool yourself).  Each
> > individual rendering system will do the appropriate thing with its
> > contextual argument.
> 
>  From my experience, I think you can basically say that any Context
>  object is a hashtable of some sort. So, it is probably feasible just
>  to use java.util.Map and, if necessary, convert the Map into the
>  concrete class when needed in the concrete implementation. The whole
>  thing looks quite trivial.
> 
> // in Velocity-specific concrete class, approximately:
> void processTemplate(Map someMap, String templateLocation, Writer out) {
>     VelocityContext vc = new VelocityContext(someMap);
>     Template t = Velocity.getTemplate(templateLocation);
>     Velocity.mergeTemplate(templateLocation, vc, out);
> }
> 
> // in FreeMarker-specific concrete class, you just use the Map directly
> // since the conversion from the Map object occurs transparently.
> void processTemplate(Map someMap, String templateLocation, Writer out) {
>     Template t = Configuration.getTemplate(templateLocation);
>     t.process(someMap, out);
> }
> 
> I mean, the fundamental pattern of usage is just so similar that
> abstracting it out and simply using whatever template engine from a
> common API is really quite a trivial exercise.

This apples to apples comparisons is a natural first step, and
provides solid examples.  An apples to zucchini comparison is also
helpful, since the use cases which don't fit a model are the ones
which cause its users the most trouble.

I ran through a few such comparisons, and a Map-based context handles
all use cases for the input processing step (objects are simply
gloried hashtables).  One doesn't always want to involve character
encodings in content generation (e.g. for binary output), so using a
generic Object interface for output is preferred to coupling the API
to Writer.  This also handles output of more complex types (e.g. DOM
trees, etc.).

public interface ContentGenerationSystem
{
    /**
     * Performs content generation, converting its inputs to the
     * appropriate CGS-specific types.
     *
     * @param context Contextual information used as inputs to the
     * content generation system.  May be <code>null</code>.
     * @param target The target to generate content for.  May be
     * <code>null</code> if <code>context</code> contained sufficient state.
     * @param output Where to send the generated content.
     */
    void generateContent(Map context, String target, Object output);
}


If multiple output types are supported, generateContent() can use the
instanceof operator to choose the appropriate action.

...
> Now, there clearly is interest on the part of some users to be able to
> try FM from Turbine. I've seen signs of that on this list and I have
> some private email that bears this out. So my earlier offer still
> stands: Get your house in order on this stuff, and I'll help you get
> it working. But the ball is currently in your court on this.

Personally, I'd be very happy to see FreeMarker available in Turbine
again, so long as its integration is supported by an active developer.
The original reason it was dropped was a lack of both developer
support and user interest.

I'd be even more happy to see a light-weight content generation
abstraction (something like what's outlined above), replacing what's
in Turbine 3.
-- 

Daniel Rall

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: Coupling of Turbine and Velocity codebases

Posted by Jonathan Revusky <jo...@revusky.com>.
Daniel Rall wrote:
> I'd like to point out the generic context implementation already
> exists in the TemplateService in Fulcrum, and is used in Turbine 3
> (and thus in Scarab).  I urge you not to give specifics of a generic
> context path even a moment's consideration, as doing so adds needless
> complexity and offers very little in return.
> 
> Any movement towards a generic context interface should use an opaque
> type, like Object or an empty marker interface (from what I saw of the
> recent TorqueComponent impl., Avalon uses these to good effect).
> Content rendering engines are inherently different, and pretending
> that they are does not make them so (read: don't fool yourself).  Each
> individual rendering system will do the appropriate thing with its
> contextual argument.

 From my experience, I think you can basically say that any Context 
object is a hashtable of some sort. So, it is probably feasible just to 
use java.util.Map and, if necessary, convert the Map into the concrete 
class when needed in the concrete implementation. The whole thing looks 
quite trivial.

// in Velocity-specific concrete class, approximately:

void processTemplate(Map someMap, String templateLocation, Writer out) {
    VelocityContext vc = new VelocityContext(someMap);
    Template t = Velocity.getTemplate(templateLocation);
    Velocity.mergeTemplate(templateLocation, vc, out);
}

// in FreeMarker-specific concrete class, you just use the Map directly
// since the conversion from the Map object occurs transparently.

void processTemplate(Map someMap, String templateLocation, Writer out) {
    Template t = Configuration.getTemplate(templateLocation);
    t.process(someMap, out);
}

I mean, the fundamental pattern of usage is just so similar that 
abstracting it out and simply using whatever template engine from a 
common API is really quite a trivial exercise.

Now, okay, there are always minor niggling details. For example, Anthony 
Eden had some various things in JPublish where he wanted to have some 
special location strings for loading templates, because JP has this 
notion of a "repository" and so on. And actually I ended up tweaking 
some things in FreeMarker to support things he wanted to do -- so that 
includes and things could work with his special template location URI's. 
Sure, things like this come up and it is good to have the active 
collaboration of the developers of the other system that you want to 
glue to...

But anyway, if you guys get your house in order to the point where you 
don't have all these points of coupling with classes in 
org.apache.velocity.*, then I'll do whatever incremental work is 
necessary to make sure that FM works there on an even footing.

As I said, the current state of things is that it's not feasible because 
of all the various coupling points. For this to fly, there has to be a 
clearly documented common API for getting at the services oif a template 
engine, and it should be just 2 or 3 subclassing points, I would say, 
and the rest of the framework should use template engine services via 
that API.

Until you have such a situation, it is pointless to tell me or somebody 
else in my position: "Submit a patch." and so on, because you don't have 
your house sufficiently in order to where somebody could really do that.

Now, there clearly is interest on the part of some users to be able to 
try FM from Turbine. I've seen signs of that on this list and I have 
some private email that bears this out. So my earlier offer still 
stands: Get your house in order on this stuff, and I'll help you get it 
working. But the ball is currently in your court on this.

Regards,

Jonathan Revusky
--
lead developer, FreeMarker project, http://freemarker.org/




---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: Coupling of Turbine and Velocity codebases

Posted by Daniel Rall <dl...@finemaltcoding.com>.
I'd like to point out the generic context implementation already
exists in the TemplateService in Fulcrum, and is used in Turbine 3
(and thus in Scarab).  I urge you not to give specifics of a generic
context path even a moment's consideration, as doing so adds needless
complexity and offers very little in return.

Any movement towards a generic context interface should use an opaque
type, like Object or an empty marker interface (from what I saw of the
recent TorqueComponent impl., Avalon uses these to good effect).
Content rendering engines are inherently different, and pretending
that they are does not make them so (read: don't fool yourself).  Each
individual rendering system will do the appropriate thing with its
contextual argument.
-- 

Daniel Rall

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: Coupling of Turbine and Velocity codebases

Posted by "Henning P. Schmiedehausen" <hp...@intermeta.de>.
Santiago Gala <sg...@hisitech.com> writes:

>I think Jetspeed should do it. In fact, there are movements in this
>direction going on already in Jetspeed-1. I like Velocity a lot, and it
>is used for basic aggregation inside jetspeed. But more and more people
>wants a JSP portal, and they are using jetspeed and developing on it.

JSP we already have. Look at the JSPService.

	Regards
		Henning


-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen          INTERMETA GmbH
hps@intermeta.de        +49 9131 50 654 0   http://www.intermeta.de/

Java, perl, Solaris, Linux, xSP Consulting, Web Services 
freelance consultant -- Jakarta Turbine Development  -- hero for hire

--- Quote of the week: "It is pointless to tell people anything when
you know that they won't process the message." --- Jonathan Revusky

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: Coupling of Turbine and Velocity codebases

Posted by Santiago Gala <sg...@hisitech.com>.
Henning P. Schmiedehausen escribió:
> Santiago Gala <sg...@hisitech.com> writes:
> 
> 
>>IMO, most of what is needed is to abstract the 
>>org.apache.velocity.context.Context class as a generic Template Context 
>>for the pull service and to substitute most "VelocityXXX" class names 
>>for "TemplateXXX"
> 
> 
> Yep. You're right on spot.
> 

Also, it looks like any "context" should implement something simple like
java.util.Map, which would ease the decoupling heavily and allow
integration with most frameworks.

> 
>>Look for instance to the VelocityDirectLayout. It only uses the Context, 
>>and the main Velocity class to get it.
> 
> 
> That's why it is called _Velocity_DirectLayout, not
> TemplateDirectLayout. One of the legacies of the old "Java Class for
> Layout/Page/Screen" models is the fact, that Templating isn't as deep
> in Turbine as it might be in other web frameworks. This has its
> advantages and its disadvantages. The fact that we have specialist
> classes for e.g. Velocity instead of a generic "TemplateLayout" class
> stems from this.
> 
> 
>>If the FM context for bean like object has a similar interface, it does 
>>not look like a daunting task.
> 
> 
> Right.
> 
> 
>>[sgala@patusan jakarta-turbine-2]$ egrep -Rl "org.apache.velocity.[^c]" 
>>src/java/
>>src/java/org/apache/turbine/services/pull/TurbinePullService.java
>>src/java/org/apache/turbine/services/velocity/TurbineVelocityService.java
> 
> 
>>Now, this work will be much better done if someone who knows the needs 
>>or specific template engines helps in the abstraction process of the 
>>context.
> 
> 
> Well, this would mean that there is _need_ for it. I personally don't
> have a need for it which means, that I use my meagre free time devoted
> to Turbine for things more interesting to me. I'm willing to review
> patches (in fact you can bet on it ;-) ) but if anyone want me to do
> this, well, contact me off-list...
> 

I think Jetspeed should do it. In fact, there are movements in this
direction going on already in Jetspeed-1. I like Velocity a lot, and it
is used for basic aggregation inside jetspeed. But more and more people
wants a JSP portal, and they are using jetspeed and developing on it.


Regards
-- 
Santiago Gala
High Sierra Technology, S.L. (http://hisitech.com)
http://memojo.com?page=SantiagoGalaBlog




---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: Coupling of Turbine and Velocity codebases

Posted by "Henning P. Schmiedehausen" <hp...@intermeta.de>.
Santiago Gala <sg...@hisitech.com> writes:

>IMO, most of what is needed is to abstract the 
>org.apache.velocity.context.Context class as a generic Template Context 
>for the pull service and to substitute most "VelocityXXX" class names 
>for "TemplateXXX"

Yep. You're right on spot.

>Look for instance to the VelocityDirectLayout. It only uses the Context, 
>and the main Velocity class to get it.

That's why it is called _Velocity_DirectLayout, not
TemplateDirectLayout. One of the legacies of the old "Java Class for
Layout/Page/Screen" models is the fact, that Templating isn't as deep
in Turbine as it might be in other web frameworks. This has its
advantages and its disadvantages. The fact that we have specialist
classes for e.g. Velocity instead of a generic "TemplateLayout" class
stems from this.

>If the FM context for bean like object has a similar interface, it does 
>not look like a daunting task.

Right.

>[sgala@patusan jakarta-turbine-2]$ egrep -Rl "org.apache.velocity.[^c]" 
>src/java/
>src/java/org/apache/turbine/services/pull/TurbinePullService.java
>src/java/org/apache/turbine/services/velocity/TurbineVelocityService.java

>Now, this work will be much better done if someone who knows the needs 
>or specific template engines helps in the abstraction process of the 
>context.

Well, this would mean that there is _need_ for it. I personally don't
have a need for it which means, that I use my meagre free time devoted
to Turbine for things more interesting to me. I'm willing to review
patches (in fact you can bet on it ;-) ) but if anyone want me to do
this, well, contact me off-list...

	Regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen          INTERMETA GmbH
hps@intermeta.de        +49 9131 50 654 0   http://www.intermeta.de/

Java, perl, Solaris, Linux, xSP Consulting, Web Services 
freelance consultant -- Jakarta Turbine Development  -- hero for hire

--- Quote of the week: "It is pointless to tell people anything when
you know that they won't process the message." --- Jonathan Revusky

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org