Hi Guillaume,
Answers inlined
And personally I am not a big fan of JSTL : I prefer java code in my
> template !
>
I used to like JSTL when I wasn't bothered by loose typing. Looked like it
was good then. But when I look back at it, I think it's crap... anyway.
> Do you think classic stripes templating and TTT could live together side
> by side ?
>
Nope. TTT is pure Java, JSP-less.
Good new is, it actually removes the requirement for Stripes layouts. I
mean, TTT templates can be composed and nested, which what stripes-layouts
basically do.
Here's an example (PageTemplate.ttt) :
<%!
String title;
ITemplate body;
%>
<html>
...
<title>
<%= title %>
</title>
...
<body>
<%= body %>
</body>
</html>
As you see the 2nd arg is... a template. When used in an expression ( <%=
tpl %> ), it is rendered inside the wrapping template.
Your action bean's event handler can do stuff like :
// create inner template for body
MyTemplate body = new MyTemplate( ... );
// create a page that includes body
PageTemplate page = new PageTemplate("hey there", body );
// return a resolution to spit out the whole page
return new TemplateResolution( page );
As you see, it's plain old Java. No fuss.
>
> Is it possible to have a fragment template used by multiple templates ?
> Example welcome..
>
Yep. As said above, any kind of nesting is possible. Let's try another
example : a template that renders a table, which itself uses another
template to render rows :
<%-- TableTemplate.ttt --%>
<%!
List<Foo> foos;
%>
<table>
<tbody>
<% for (Foo f : foos) { %>
<%= new RowTemplate(f) %>
<% } %>
</tbody>
</table>
And the Row template :
<%-- RowTemplate.ttt --%>
<%!
Foo foo;
%>
<tr>
<td><%= foo.getProp1() %></td>
<td><%= foo.getProp2() %></td>
<td><%= foo.getProp3() %></td>
</tr>
Rendering the whole table goes like
List<Foo> foos = ... ;
return new TemplateResolution( new TableTemplate( foos ) );
Looks far better to me than a dumb <jsp:include/>... The only approaching
stuff is JSP tags. Unfortunately you still need JSPs to use them...
Cheers
Rémi
>
>
> Regards
> Guillaume
>
>
>
>
> On Mon, Aug 3, 2015 at 2:52 PM, VANKEISBELCK Remi <[email protected]> wrote:
>
>> Hi folks,
>>
>> I'm trying out something quite cool, I though I'd share with you.
>>
>> Pretty long email, but I think this could be a killer feature for our
>> favourite fwk.
>>
>> For some of you who don't know Play2 <https://www.playframework.com>,
>> they have (amongst very good other stuff) a neat feature called Scala
>> Templates
>> <https://www.playframework.com/documentation/2.0/ScalaTemplates>.
>>
>> The idea is to have statically typed templates, just like everything
>> else. The template defines a signature (named arguments), and it ends up as
>> a actual function. You write the template in Scala, using a mix of html and
>> code, and you must define the template's signature. You then call the
>> function to render the template, passing any required argument. Simple, and
>> safe.
>>
>> This is not so common in MVCs. I don't know any pure Java fwk doing this.
>>
>> It has great advantages, I won't explain the benefits of Type Safety
>> here, but it's definitely a killer feature. Type safety applied to web page
>> templates !
>>
>> To be honest, this almost got me. For a moment I thought, damn, we're
>> f*cking laaate with Stripes. I was about to switch to Play for good.
>>
>> But before this, and using a few days off I had, I wanted to figure out
>> how this would work in pure Java. Play is written in Scala which is a
>> completely different language, allowing for those neat templates. But how
>> can we do this in good old Java ?
>>
>> So I started by creating a "typed text templating framework" that allows
>> to write templates using a subset of the JSP syntax, and to compile them to
>> strong-typed Java code.
>>
>> The name is TTT, which stands for Typed Text Templates.
>>
>> Here's how a simple template looks like (MyTemplate.ttt) :
>>
>> <%!
>> String foo;
>> %>
>> <div class="my">
>> <%= foo %>
>> </div>
>>
>> The JSP declaration ( "<%!" ) is used to define the signature of the
>> template. This one takes a single argument "foo" of type String. Then, it
>> has some text (html actually) and an expression. As you imagine, the
>> expression is replaced by its value when the template gets rendered.
>>
>> The TTT compiler can be invoked in order to generate a fully-functional
>> Java class, that you can use in your code to render the template :
>>
>> // somewhere in my code
>> Writer out = ...;
>> new MyTemplate("hey there !").render(out);
>>
>> As you see, the signature of the template maps to constructor arguments,
>> and you have a render(out) method to spit out the template to a Writer. You
>> can also compose templates, but I won't explain this here for the sake of
>> brevity (really ?).
>>
>> So far so good. I can :
>> 1/ write my templates almost like a JSP
>> 2/ compile the templates to Java code
>> 3/ invoke the generated code and render the templates to a Writer
>>
>> Now, how does this integrate with Stripes ? Can we remove JSPs and use
>> TTT templates instead ? Well, yes, we can !
>>
>> Rendering a template from an Action looks like :
>>
>> public Resolution doSomething() {
>> // do stuff
>> ...
>> return new TemplateResolution( new MyTemplate("hello there") );
>> }
>>
>> Very easy : the class TemplateResolution (implements Resolution) does the
>> job. All you need to do is pass a template to its sole constructor.
>>
>> Let's try a to apply our good old "pre-action" pattern to this, with a
>> simple action+template :
>>
>> public class MyAction implements ActionBean {
>>
>> public String getStuff() {
>> ...
>> }
>>
>> @DefaultHandler
>> public Resolution doIt() {
>> return new TemplateResolution( new MyTemplate(this) );
>> }
>> }
>>
>> And now the template (MyTemplate.ttt) :
>>
>> <%!
>> // template needs the action
>> MyAction myAction;
>> %>
>> <html>
>> ...
>> <div>
>> <%= myAction.getStuff() %>
>> </div>
>> ...
>> </html>
>>
>> Again, very easy :
>> 1/ The action bean returns a TemplateResolution, passing itself to
>> MyTemplate's constructor
>> 2/ The template uses the bean, declated as an argument, as any other Java
>> object.
>>
>> The big (huge) difference here with the current approach using JSP is
>> that everything is statically typed.
>>
>> Let's compare this to the "regular" JSP approach :
>>
>> public class MyAction implements ActionBean {
>>
>> public String getStuff() {
>> ...
>> }
>>
>> @DefaultHandler
>> public Resolution doIt() {
>> return new ForwardResolution("/WEB-INF/jsp/my.jsp");
>> }
>> }
>>
>> And the JSP :
>>
>> <%@ page ... %>
>> <html>
>> ...
>> <div>
>> ${actionBean.stuff}
>> </div>
>> ...
>> </html>
>>
>> Several problems here :
>> * in the controller, the forward is... a plain string. The JSP could even
>> not be there at runtime, who knows...
>> * no args are passed to the JSP when forwarding. The context is usually
>> the request scope, which acts as a loose-typed hashmap...
>> * in the JSP, what is "actionBean" ? you need to assume somebody has
>> tossed an object that has a "stuff" property into some scope (request ?
>> session ? app ? ...). Again, no compile-time help. Ok you could use a
>> scriplet and cast, but still : do you have a guarantee it's there, and it's
>> what you want ?
>>
>> The TTT approach removes all those issues, and "fills the blank" between
>> the Controller and the View layers. Using this technique, it's all
>> statically typed. No more expectations about the presence of an attribute
>> or anything.
>>
>> It also brings lots of other benefits :
>> * more reusable views
>> * container-independent : same technology for serving web pages or
>> spitting out emails or anything
>> * support for composite templates (nested) - think "typed Stripes layouts"
>> * ...
>>
>> Of course, the Stripes taglib doesn't work in .ttt templates, so it has
>> to be reimplemented as pure Java APIs, useable directly from the templates.
>> It's a bit long, there's a lot of them, and the mapping ain't necessarily
>> 1:1. But it's a good opportunity to rethink the tags, and craft a nice,
>> fluent API.
>>
>> An example of s:form. The classic one, JSP+tags :
>>
>> <%@ taglib prefix="s" ... %>
>> ...
>> <s:form beanclass="<%=MyAction.class%>">
>> Fill me
>> <s:text name="myProp"/>
>> and
>> <s:submit name="doIt" value="Click Me"/>
>> </s:form>
>>
>> And the TTT equivalent :
>>
>> <%! ... %>
>> <%
>> StripesTags stripes = new StripesTags(out);
>> try ( Form f = stripes.form(MyAction.class).build() ) {
>> %>
>> Fill me
>> <%= f.text( "myProp" ) %>
>> and
>> <%= f.submit( "doIt", "Click Me" ) %>
>> <% } %>
>>
>> As you see, it's using standard Java code in order to call the Stripes
>> "tags". I'm trying various approaches, like the try-resource for tags that
>> have a body. Again, it's a good opportunity to review the existing tags,
>> and design clean APIs for those.
>>
>> It is a pretty ambitious project : there are many domains involved
>> (compilation, IDE, etc). But it is challenging, and I think it really
>> provides added value.
>>
>> Stripes is getting old, and without such kind of new features, it'll
>> probably die slowly in favor of Spring or any other MVC.
>>
>> I looked at Spring to see if I could integrate in there. Could be done
>> too, and would work just fine. But I think SpringMVC is a beast, it's too
>> big, and I like the programming model and simplicity of Stripes.
>>
>> The project is open and free for anyone to try out / contribute :
>> https://github.com/pojosontheweb/ttt
>>
>> For the moment I have :
>> * template compiler : creates Java source code from .ttt files
>> * maven mojo : compiles templates when building the app (generate-sources
>> phase)
>> * IntelliJ IDEA plugin : compile on save
>>
>> It's still mostly a POC and needs some work to make it production-grade,
>> but it's functional enough to play with.
>>
>> What do you think folks ?
>>
>> Cheers
>>
>> Rémi
>>
>>
>>
>>
>> ------------------------------------------------------------------------------
>>
>> _______________________________________________
>> Stripes-development mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/stripes-development
>>
>>
>
>
> ------------------------------------------------------------------------------
>
> _______________________________________________
> Stripes-development mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/stripes-development
>
>
------------------------------------------------------------------------------
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development