Love this idea! I too have been trying out Play2 and I would love to see this TTT feature added to Stripes.
Joaquin Valdez [email protected] <mailto:[email protected]> > On Aug 3, 2015, at 6:52 AM, 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 <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
