[stringtemplate-interest] Does StringTemplate support components?

John Snyders jjsnyders at rcn.com
Sat Dec 23 20:54:42 PST 2006


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org:8080/pipermail/stringtemplate-interest/attachments/20061223/709157c8/attachment.html 


More information about the stringtemplate-interest mailing list