[stringtemplate-interest] Does StringTemplate support components?

Bill Venners bv-svp at artima.com
Wed Dec 27 16:45:38 PST 2006


Hello,

I like the idea of components as well, but not the kind you described  
originally whereby you call Java code to get attributes. I have a  
notion of a view is that it is a tree of component objects, each of  
which encapsulates data and the ability to render that data in  
various themes and locales. So a component would be a Java class that  
requires all data needed by its template(s) to be passed to its  
constructor up front, and it would store that data in instance  
variables. When someone calls its render(Writer out) method, it would  
render the appropriate template with that instance data. Each  
component would do the enforcement of the separation of model and  
view that I really like about ST.

What ST pushed me towards is having those components just be holders  
of data. So the Java programmer would build up a tree of these data- 
holding components. The template designers would create a conceptual  
tree of templates in a way, by having templates refer to templates.  
Often the template tree will have the same structure as the data- 
holder objects tree.

So why not let each component keep track of its own data and  
templates, and do the rendering of itself. What I'd need in ST is a  
way to call render() on components I suppose, and I don't believe I  
have a way to do that in ST, because it would open up the possibility  
of calling any arbitrary Java code.

The other thing that bugs me a bit is that I can't know at compile  
time if I'm using a parameter in a template that doesn't exist in the  
data. I'm tempted towards the JSP approach of taking some template  
and translating it into print statements that could be called by the  
render method of component objects. These would not compile if there  
were naming problems.

I know that Terrence came to the design of ST while solving real  
problems of web pages and code generation. Is there any reason why  
doing such a component approach might be less useful in practice than  
the ST approach?

Thanks.

Bill
----
Bill Venners
President
Artima, Inc.
http://www.artima.com


On Dec 27, 2006, at 10:28 AM, Adam Bennett wrote:

> Thanks for answering my question, John.  Let me summarize what I  
> heard:
> ---
> StringTemplate does not support "componentization" if we define a  
> single component as a combination of .java code and a .st template  
> that is independent of the enclosing template that invoked it.   
> This lack of support is intentional because it creates a situation  
> where the view is pulling data from the model which is an anti- 
> pattern that StringTemplate wishes to prevent.
> ---
>
> Fair enough.  Even so I still find the idea of componentization  
> attractive.  I have this dreamy vision of programmers cranking out  
> reusable components and web designers mixing and matching them.   
> But perhaps it is not a worthwhile goal.  Although I am not too  
> complelled by the order of invocation argument, I can now see at  
> least one short coming of this sort of componentization:  
> exceptions.  If the web server begins to evaluate a template and  
> stream it to the client what happens if there is an exception while  
> evaluating a sub component?  At this point the response is  
> committed so we can't redirect them to an error page.  If we had  
> gotten all the data up front as StringTemplate requires this would  
> not be a problem.
>
> Thanks enlightening me.
> - Adam Bennett
>
>
> From: John Snyders [mailto:jjsnyders at rcn.com]
> To: Adam Bennett [mailto:adamb at videx.com], stringtemplate- 
> interest at antlr.org
> Sent: Sat, 23 Dec 2006 20:54:42 -0800
> Subject: RE: [stringtemplate-interest]Does StringTemplate support  
> components?
>
> I'll try to answer.
> -----Original Message-----
> From: stringtemplate-interest-bounces at antlr.org  
> [mailto:stringtemplate-interest-bounces at antlr.org]On Behalf Of Adam  
> Bennett
> Sent: Saturday, December 23, 2006 2:49 AM
> To: stringtemplate-interest at antlr.org
> Subject: Re: [stringtemplate-interest]Does StringTemplate support  
> components?
>
> I really appreciate all the suggestions but I haven't heard the  
> answer yet.  I'll try to reformulate my the question:
>
> Question 1) From my reading, it appears that StringTempate supports  
> calling other templates as if it were a subroutine, right?
> [John Snyders] Correct
>   I infer this from the "Expressions" document where it is talking  
> about "Template References":
>
> "the enclosing page template would automatically create an instance  
> of the referenced template and insert it"
>
> What I am focusing on here is "automatically create an instance".   
> Beautiful.  Less coding.
>
> Question 2) The documentation goes on to describe 2 ways of getting  
> the necessary attributes to the subroutine template.
> 1) "Accessing Attributes Of Enclosing Template"
> [John Snyders] In a group file the templates must declare all the  
> attributes they use so this really applies to the non-group (do  
> these have a name?) .st templates. Essentially the attributes  
> defined by the controller are globally available to all templates  
> (unless hidden by an argument explicitly passed to the template in  
> the call).
> 2) "Passing Parameters To Another Template"
> [John Snyders] This can be done with templates in .st or .stg files
>
> Are there any other ways?
> [John Snyders] Not really
>  You see, what I am looking for is a way to help the web designers  
> work independently of the programmers.  Here's a scenario to  
> describe what I mean.  Let's say that our web application handles  
> the URL "/OurWebApp/account/summary.page" with Java code like this:
>
> StringTemplate st = group.GetInstanceOf("account/summary.st");
> ... do some database queries
> st.setAttribute("foo", queryResult1);
> st.setAttribute("bar", queryResult2);
> ... render the template and send it to the client browser
>
> The above code is maintained by the programmers.  The web designers  
> can tweak the template text to their hearts content.  Initially it  
> looks like:
> <html>
> <body>
> ...
> $foo$
> $bar$
> ...
> </body>
> </html>
>
> But wait!  The web designer is changes her [artistic] mind and  
> decides to take the summary page the next level.  She wants to show  
> the users account balance so she makes a call to the  
> accountBalanceBox template.
> <html>
> <body>
> ...
> $foo$
> $bar$
> $accountBalanceBox()$
> ...
> </body>
> </html>
> [John Snyders]  But this is not a presentation change! The web  
> designer is responsible for presentation. The content of the page  
> (the foo and bar and account balance) are the responsibility of the  
> product owner which may be the customer and it is up to the web  
> designer and programmer together to implement. In other words this  
> is a change to the data model available to the page(s).
>
>
> But accountBalanceBox needs a $dollars$ attribute.  This can only  
> be determined by getting the user ID from the HttpSession and then  
> querying the database for it.  But that's the job of the  
> programmer.  If we have support for true componentization then the  
> Java code that handles summary.page should NOT need to set the  
> $dollars$ attribute.  The general principle here is separation of  
> concerns (http://en.wikipedia.org/wiki/Separation_of_concerns).  If  
> accountBalanceBox is made to be a logical component, which includes  
> both a template as well as some Java code, it gives web designers  
> full freedom to mix and match the components that have been  
> provided by the programmers.
> [John Snyders] but from the HTML/HTTP point of view summary.page is  
> monolithic and this is what ST must generate. You can have one  
> template for the overall page and another seperate template for the  
> accountBalanceBox. You can have component code for getting foo and  
> bar and a seperate component for getting the account balance but  
> there is just one HTTP request for the summary page and one HTML  
> reply that includes both information.
>
> I think one of the suggestions was to have the controller call the  
> account balance component which would invoke its own ST template  
> with its own model and return a string. That string would then be  
> passed as an attribute to the overall page template. I don't like  
> doing it this way because I think that the page should be generated  
> with one call to string template.
>
> My feeling is that the controller needs to know about all the model  
> data that a given page needs. It may not know the details of what  
> is in the model but it knows which components to call to get it. So  
> it calls one component to get the foo and bar then calls another to  
> get the account balance. These components contribute to the model  
> in the form of attributes. I have been using ST for generating the  
> presentation of a web app and this is more or less how I do it. I  
> started with the non-group templates but quickly moved to the group  
> format.
>
> A concern may be a large number of arguments to pass around. There  
> are 2 things that can help here. One is that when calling a  
> template you can use ... to have attributes pass through to called  
> templates. The other is that attributes can reference arbitrarily  
> deeply nested object structure. So you could have your top level  
> template with a single argument called model and have that object  
> (or Map) contain all the different parts of the model as children
> Ex:
> $model.foo$
> $model.bar$
> $accountBalanceBox(balance=model.balance,...)$
>
> Some other options (I have not tried these yet) to reduce  
> interaction between components:
>
> If using AJAX the request for the foo and bar data may be totally  
> different from the accountBalanceBox. With AJAX much of the  
> controller moves to the client. In the extreme the dynamic part of  
> the web app is just serving data and there is no need for ST or any  
> template engine.
>
> If you don't like the controler knowing what parts of the model is  
> needed for a given page that information could be configured in an  
> external data file (like a struts tiles def) which the controler  
> reads. Then if the controler knows what to call to get model parts  
> a, b, and c the page designer can decide that the account summary  
> page needs a and b and the orders page needs b and c.
>
> So I think the mechanism I am after is some sort of hook.  As  
> StringTemplate encounters accountBalanceBox it calls my Java  
> function which gives me a chance to provide the necessary  
> attributes.  Such a hook might look like this:
>
> void templatePreprocess(StringTemplate st, StringTemplateContext  
> context)
> {
>   if (st.getName().equals("accountBalanceBox"))
>   {
>     HttpSession session = context.getAttribute("session");
>     int userID = session.getAttirbute("userID");
>     st.setAttribute("dollars", database.getBalance(userID));
>     return;
>   }
>   ...
> }
>
> Does such a mechanism exist?
> [John Snyders] No,  All model data must be given to the template  
> before it is invoked with toString (or write)
>
> Section 7.1 of Enforcing Strict ModelView Separation in Template  
> Engines describes why pulling data from the template breaks  
> separation.
>
> Once you have more than one hook being called there can be order  
> dependent interactions that can cause problems. For ages hook1 is  
> called before hook2 and all is well. Then one day the page designer  
> moves things around and now hook2 is called before hook1 and the  
> code breaks. Perhaps you are now trying to get something out of the  
> session before it is there. In many case there are no order  
> dependencies but in general it is not possible for the developer to  
> defensively code so that the code can be called in any order.
>
>
> Thanks much.
> - Adam
>
> I have been using ST for a few months now for generating HTML. It  
> takes some getting used to but I like it better than what I had  
> done in the past which includes JSP and JSP/Struts.
>
> -John
>
>
>
> _______________________________________________
> stringtemplate-interest mailing list
> stringtemplate-interest at antlr.org
> http://www.antlr.org:8080/mailman/listinfo/stringtemplate-interest






More information about the stringtemplate-interest mailing list