DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Template-Based PDF Document Generation in Java
  • Template Design Pattern or Template Method Design Pattern in Java
  • Spring Beans With Auto-Generated Implementations: How-To
  • Introduction to Spring Boot and JDBCTemplate: JDBC Template

Trending

  • Why Your DLP Policies Fall Short the Moment AI Agents Enter the Picture
  • What Is Plagiarism? How to Avoid It and Cite Sources
  • Exactly-Once Processing: Myth vs Reality
  • How to Format Articles for DZone
  1. DZone
  2. Coding
  3. Java
  4. Java Templating With Rocker

Java Templating With Rocker

This tutorial will dive into templating with Rocker, a Java 8 template engine designed to be statically typed, and the pros and cons of using this tool.

By 
Michael Scharhag user avatar
Michael Scharhag
·
May. 15, 18 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
17.4K Views

Join the DZone community and get the full member experience.

Join For Free

In this post, we will have a quick look at Rocker, a statically typed and fast Java 8 template engine.

Required Dependencies

To get started with Rocker, we need to add the following dependencies to our project:

<dependency>
    <groupId>com.fizzed</groupId>
    <artifactId>rocker-runtime</artifactId>
    <version>0.24.0</version>
</dependency>

<!-- for hot-reloading support in development -->
<dependency>
    <groupId>com.fizzed</groupId>
    <artifactId>rocker-compiler</artifactId>
    <version>0.24.0</version>
</dependency>


We also need the Rocker Maven plugin, which converts Rocker templates to Java code:

<build>
    <plugins>
        <plugin>
            <groupId>com.fizzed</groupId>
            <artifactId>rocker-maven-plugin</artifactId>
            <version>0.24.0</version>
            <executions>
                <execution>
                    <id>generate-rocker-templates</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>


Creating the First Templates

We will start with a simple example containing two Rocker templates and a Java class.

In the first template (main.rocker.html), we define the basic page structure:

@args (String title, RockerBody content)

<html>
  <head>
    <title>@title</title>
  </head>
  <body>
    @content
  </body>
</html>


This template has two parameters: The page title and a RockerBody element named content. The content parameter is basically a sub-template that is added to the <body> tag.

Now we create another template (basic.rocker.html) that defines the content that is passed to our first template:

@args (String name)

@views.main.template("Basic example") -> {
    <h1>Hello @name!</h1>
}


This template has a single name parameter that is written to a <h1> tag. We reference the first template (main.rocker.html) with @views.main and use the template(..) method to render it. "Basic example" will be passed as title parameter. The content parameter is defined within the curly braces.

Rendering Rocker templates

Rocker templates are converted to Java code. This can be done using the following Maven command:

mvn generate-sources


This generates a Java class for each template in the target/generated-sources/rocker directory.

Now we can render our templates using Java code:

public class Main {

    public static void main(String... args) throws Exception {

        // The template "basic.rocker.html" got converted to the class named "basic"
        // which is located in the "views" package

        String result = views.basic.template("John")
            .render()
            .toString();

        System.out.println(result);
    }
}


The output we get looks like this:

<html>
    <head>
        <title>Basic example</title>
    </head>
    <body>
        <h1>Hello John!</h1>
    </body>
</html>


A bit of a problem with this approach is that you need to run mvn generate-sources everytime you make a change in your template files. Also note, that your Java code might not compile if the code generation fails because you have an issue in one of your templates.

Another possible approach is to use hot reloading and reference the templates dynamically via file names.

In this case, the Java code looks like this:

public class Main {

    public static void main(String... args) throws Exception {

       // Enable hot reloading
    RockerRuntime.getInstance().setReloading(true);

    // Reference via string instead of using generated code
    String result = Rocker.template("views/basic.rocker.html")
        .bind("name", "John")
        .render()
        .toString();

    System.out.println(result)
    }
}


The output we get is exactly the same.

Expressions

Assume we have a simple User class that contains the methods getFirstName() and getLastName(). In the following example we see how we can work with the User object in a Rocker template:

@import com.mscharhag.rockerexample.*

@args (User user)

@views.main.template("Expressions") -> {
    <ul>
        <!-- first name -->
        <li>@user.getFirstName()</li>

        <!-- first three letters of first name -->
        <li>@user.getFirstName().substring(0, 3)</li>

        <!-- first name and last name -->
        <li>@user.getFirstName() @user.getLastName()</li>

        <!-- using a variable-->
        @name => {
            @user.getFirstName() @user.getLastName()
        }
        <li>@name</li>

    </ul>
}


Conditions

Rocker supports the standard Java if-else flow structure as the following example shows:

@import com.mscharhag.rockerexample.*

@args (User user)

@views.main.template("Conditions") -> {
    @if (user.getFirstName().length() > 10) {
        <p>Long first name</p>
    } else {
        <p>short first name</p>
    }
}


Loops

Rocker templates support different forms of loops:

@import com.mscharhag.rockerexample.*
@import java.util.*

@args (List<User> users)

@views.main.template("Loops") -> {
    <ul>
        <!-- standard for loop -->
        @for (int i = 0; i < users.size(); i++) {
            <li>@users.get(i).getFirstName()</li>
        }

        <!-- standard 'for each' loop -->
        @for (User user : users) {
            <li>@user.getFirstName()</li>
        }

        <!-- for each loop with additional loop information

        <li>0: John, first: true, last: false</li>
        <li>1: Martin, first: false, last: false</li>
        <li>2: Anna, first: false, last: true</li>
        -->
        @for ((i, user) : users) {
            <li>@i.index(): @user.getFirstName(), first: @i.first(), last: @i.last()</li>
        }

    </ul>
}


The last loop is a special variation of Java's for-each loop. A second index parameter (named i in the example) can be used to access current iteration information.

Conclusion

Rocker can be definitively an option if you are looking for a Java template engine. According to the benchmark on the Rocker GitHub repository, Rocker is a lot faster than other Java template engines like Freemarker or Velocity. The comprehensive documentation is another good point to mention.

The fact that Rocker compiles to Java and allows you to pass data to views in a typesafe way is quite interesting. On one side this is useful because it helps to reduce bugs. On the other side, the same feature annoyed me a bit, while I was writing the examples. Whenever I made code changes that affected Rocker templates (e.g. by changing the name of a method that was called within a Rocker template) the templates stopped compiling. In some situations, this again stopped my Java code from compiling (because it was using the classes generated by Rocker). This is expected but it can break my preferred workflow of writing Java code first and fixing the templates later. Referencing templates via file names instead of using the generated classes solved this problem (but also throws away the type checking at compile time).

Java (programming language) Template

Published at DZone with permission of Michael Scharhag. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Template-Based PDF Document Generation in Java
  • Template Design Pattern or Template Method Design Pattern in Java
  • Spring Beans With Auto-Generated Implementations: How-To
  • Introduction to Spring Boot and JDBCTemplate: JDBC Template

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook