[stringtemplate-interest] Does StringTemplate support components?
Bill Venners
bv-svp at artima.com
Wed Dec 27 17:32:51 PST 2006
Hello,
One more note on components. I'm aware I can call toString() on a
component object, and get the behavior I described. But that of
course means you build Strings in memory first and then write them to
the output stream. It would be nice if I could write it to the output
stream to begin with, which is why I want to be able to call render
(Writer out). (I believe this still holds to ST's philosophy of
separation of model and view, so long as <component>.render(Writer
out) only renders another template with data already assembled by
that component.) I did notice somewhere in the ST documentation that
this is possible with ST itself, but as far as I know, only if you
pass a tree of data-holders to an outermost ST template that then
runs the show, likely by invoking templates in a structure similar to
the data-holder tree's structure.
And I meant Terence, not Terrence. Sorry.
Bill
On Dec 27, 2006, at 4:45 PM, Bill Venners wrote:
> 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
>
>
>
>
> _______________________________________________
> 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