Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreWith the release of Spring Boot 1.1.0.M2 came the support for the new template engine that Groovy 2.3 provides. In this post, we will describe the benefits of using such an engine and of course how you can use it in Boot.
All the source code in this post is available on GitHub, so feel free to clone the repository and give it a try:
git clone https://github.com/melix/springboot-groovytemplates.git
cd springboot-groovytemplates
./gradlew run
Then open your browser on http://localhost:8080
This application is fully written in Groovy and also makes use of GORM for Boot, but it is of course possible to use Groovy only for the templating part and write the rest of the application in Java. Starting from now, we will only focus on the templating aspect of this project.
Integrating with Groovy 2.3 templates in Spring Boot is very easy. You just need to add a dependency to the groovy-templates
module in your build file. For example, if you use Gradle, just use this:
dependencies {
compile "org.codehaus.groovy:groovy:${groovyVersion}"
compile "org.codehaus.groovy:groovy-templates:${groovyVersion}"
compile "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"
compile "org.grails:gorm-hibernate4-spring-boot:1.0.0.RELEASE"
runtime "com.h2database:h2:1.3.173"
}
The Groovy markup template engine provides an innovative templating system based on the builder syntax. It offers various key features:
and more! you can find a full list of the features of this template engine in the documentation. The templates are basically Groovy code with special support for the template use case.
Let's start with a very simple example, where we want to display an index with a simple message containing the version numbers of Spring Boot and Groovy currently in use:
yieldUnescaped '<!DOCTYPE html>'
html {
head {
title('Spring Boot - Groovy templates example')
link(rel: 'stylesheet', href: '/css/bootstrap.min.css')
}
body {
div(class: 'container') {
div(class: 'navbar') {
div(class: 'navbar-inner') {
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html',
'Groovy - Template Engine docs')
a(class: 'brand',
href: 'hhttp://projects.spring.io/spring-boot/') {
yield 'Spring Boot docs'
}
}
}
div("This is an application using Boot $bootVersion and Groovy templates $groovyVersion")
}
}
}
On the first line, you can read the yieldUnescaped
instruction. It instructs the renderer to render the argument as is. This instruction can be used to render any kind of text based contents. Here, it is used to render the doctype declaration of our HTML file, but you can really use it to render anything. The template engine provides a number of helper functions like yield
, which are described in the documentation.
The rest of the template consists of a hierarchical structure matching the HTML output, making it very natural to render HTML contents. For example, the code: link(rel: 'stylesheet', href: '/css/bootstrap.min.css')
will be rendered as:
<link rel='stylesheet' href='/css/bootstrap.min.css'/>
Similarily, this:
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html',
'Groovy - Template Engine docs')
will be rendered as:
<a class='brand' href='http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html'>Groovy - Template Engine docs</a>
Note how the attributes in the template map to tag attributes in the rendered HTML. The last argument corresponds to the body of the tag. Alternatively, it is possible to use the yield
instruction to render the body of the tag:
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html') {
yield 'Groovy - Template Engine docs'
}
The choice often depends on whether you have nested contents to render or not. But so far, all the contents that our template generates is static. The last part of the template is more interesting:
div("This is an application using Boot $bootVersion and Groovy templates $groovyVersion")
As you guessed, this will be rendered as:
<div>This is an application using Boot 1.1.0.M2 and Groovy templates 2.3.2</div>
The template, here, makes use of two variables which are found in the model:
Those are exposed by our application as variables in the template, so let's see how we do this.
The only thing that we have to do is creating a controller which will render our view, and as usual with Spring Boot, it's a matter of a few lines of code:
package sample
import org.springframework.boot.Banner
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.servlet.ModelAndView
@Controller
class SampleController {
@RequestMapping("/")
def home() {
new ModelAndView(
"views/home",
[bootVersion: Banner.package.implementationVersion,
groovyVersion: GroovySystem.version])
}
}
Our home
method returns a ModelAndView
instance, and the model only contains two elements, which are the Spring Boot version and well as the Groovy version. The view is automatically found thanks to its reference, views/home
. Spring Boot expects the view to be found in src/main/resources/templates/views
. Can it be easier?
In real life, templates are unlikely to be that simple. You will have entities, databases, CRUD operations, etc... So the next step is to show you how you can use the new template engine to render a model which is more complex. For that, we made use of GORM, so we will start by defining an entity named Person
:
package sample
import grails.persistence.*
@Entity
class Person {
String firstName
String lastName
}
And what we will want to do is, for example:
So we will need two templates: one for listing persons, the other for creating a person (or editing). The list example is interesting because it will let us show you how you can iterate on a list in the template. So before that, let's create a controller with the list operation:
@Controller
@RequestMapping("/person")
class PersonController {
@RequestMapping("list")
def list() {
new ModelAndView('views/person/list', [persons: Person.list()])
}
}
You can see that similarily to what we did in the simple example, we return a ModelAndView
example, but this time, the model contains a list of persons. So let's see what the template looks like:
yieldUnescaped '<!DOCTYPE html>'
html {
head {
title('Spring Boot - Groovy templates example')
link(rel: 'stylesheet', href: '/css/bootstrap.min.css')
}
body {
div(class: 'container') {
div(class: 'navbar') {
div(class: 'navbar-inner') {
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html',
'Groovy - Template Engine docs')
a(class: 'brand',
href: 'hhttp://projects.spring.io/spring-boot/') {
yield 'Spring Boot docs'
}
}
}
ul {
persons.each { person ->
li {
a(href:"/person/$person.id", "$person.lastName $person.firstName")
}
}
}
div {
a(href:'/person/add', 'Add new person')
}
}
}
}
Most of the template is actually corresponding to the decoration of the page, and copied from the original template. At this point, you may wonder what you can do to improve this, but we will come back to that later, and focus on the most interesting part of this template, the iteration:
ul {
persons.each { person ->
li {
a(href: "/person/$person.id", "$person.lastName $person.firstName")
}
}
}
Looping over the persons
variable is done thanks to the traditional each
method that Groovy developers are used to. This is normal, because the templates are in fact Groovy code! So we can iterate on the persons, we give a name (person
) to the current person in the iteration, then use it inside an a
tag.
With several persons in database, the resulting HTML would be something like this:
<ul>
<li><a href='/person/1'>John Doe</a></li>
<li><a href='/person/2'>Bob Dylan</a></li>
<li><a href='/person/3'>Guillaume Laforge</a></li>
<li><a href='/person/4'>Graeme Rocher</a></li>
<li><a href='/person/5'>Dave Syer</a></li>
</ul>
So if you are used to JSPs, GSPs and any kind of HTML-like templating system, you can immediately see that this template engine will release you from the infamous issue of having to deal with opening/closing tags. And this is just a beginning... As an illustration of how you can simplify things, we will introduce you to the layout mechanism.
If you remember, we actually have two templates that share a common structure. They both use Twitter Bootstrap, they both share the same menu, and eventually, the only thing that changes is the page title and the main body. What if we could extract this from our templates and share it?
Layouts are made for this. So let's extract the common part of our template into a main.tpl file that we will save into src/main/resources/templates/layouts:
yieldUnescaped '<!DOCTYPE html>'
html {
head {
title(pageTitle)
link(rel: 'stylesheet', href: '/css/bootstrap.min.css')
}
body {
div(class: 'container') {
div(class: 'navbar') {
div(class: 'navbar-inner') {
a(class: 'brand',
href: 'http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html',
'Groovy - Template Engine docs')
a(class: 'brand',
href: 'hhttp://projects.spring.io/spring-boot/') {
yield 'Spring Boot docs'
}
}
}
mainBody()
}
}
}
This looks very similar to a standard template, but you can actually find two special things:
title(pageTitle)
where pageTitle
is expected to be the page title that we want to givemainBody()
, which will cause rendering of the main body for pages using that layout. Note the parenthesis which are important.Now let's update the home page template to use this layout:
layout 'layouts/main.tpl',
pageTitle: 'Spring Boot - Groovy templates example with layout',
mainBody: contents {
div("This is an application using Boot $bootVersion and Groovy templates $groovyVersion")
}
You can see that we call the layout
method and provide it with several arguments:
layouts/main.tpl
)pageTitle
, a simple stringmainBody
, using the contents
blockUse of the contents
block will trigger the rendering of the contents of mainBody
inside the layout when the mainBody()
instruction is found. So using this layout file, we are definitely sharing a common, structural pattern, against multiple templates. As an illustration, let's see how the list.tpl
template now looks like:
layout 'layouts/main.tpl',
pageTitle: 'List persons',
mainBody: contents {
ul {
persons.each { person ->
li {
a(href:"/person/$person.id", "$person.lastName $person.firstName")
}
}
}
div {
a(href:'/person/add', 'Add new person')
}
}
Of course, layouts are themselves composable, so you can use layouts inside layouts...
In this post, we have showed you how Spring Boot makes it very easy to use the new template engine that Groovy introduced in Groovy 2.3. This template engine offers a very natural and powerful syntax to generate any kind of text based contents. A full description of the capabilities of the template engine can be found in the Groovy documentation and an alternative application using the same technology can be found in the Spring Boot samples.
Last but not least, native support for this template engine is coming into Spring 4.1! So expect more Groovy love in the future!