Java Template Engine [JTE]

The Java Template Engine (jte) is a secure and lightweight template engine designed for Java and Kotlin applications. It emphasizes minimal syntax, leveraging existing language features to make templates intuitive and maintainable.

for more info visit official doc - https://jte.gg

Some of the features of JTE -

  1. Performance: JTE compiles templates to Java bytecode, resulting in efficient runtime execution.

  2. Compile-time checking: Catch errors at compile time rather than runtime.

  3. Lightweight: Minimal overhead and dependencies.

  4. Hot reloading: See changes immediately without restarting your application.

  5. Pre-compilation: Improve startup times by pre-compiling templates.

Integrating jte into a Spring Boot Application

  1. Create spring boot project with web starter.

  2. add the following dependency to use jte

 <dependency>
      <groupId>gg.jte</groupId>
      <artifactId>jte</artifactId>
      <version>3.1.12</version>
 </dependency>
<dependency>
      <groupId>gg.jte</groupId>
      <artifactId>jte-spring-boot-starter-3</artifactId>
      <version>3.1.12</version>
</dependency>

It will also create jte folder in application, in which we need to store our templetes.

  1. Add the following plugin along with spring boot maven plugin

<plugin>
        <groupId>gg.jte</groupId>
        <artifactId>jte-maven-plugin</artifactId>
        <version>3.1.12</version>
        <executions>
          <execution>
            <id>jte-generate</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>generate</goal>
            </goals>
            <configuration>
              <sourceDirectory>${project.basedir}/src/main/jte</sourceDirectory>
              <contentType>Html</contentType>
              <binaryStaticContent>true</binaryStaticContent>
              <targetResourceDirectory>${project.build.outputDirectory}</targetResourceDirectory>
            </configuration>
          </execution>
        </executions>
  </plugin>
  1. Create a template in jte directory with extension of .jte.

template - index.jte in src/main/jte

@param String name // for parameters from model map

<!DOCTYPE html>
<html>
<head>
    <title>Hello JTE</title>
</head>
<body>
    <h1>Hello, ${name}!</h1>
</body>
</html>
  1. To view this on browser we need to create a controller also

@Controller
public class HomeController {

    @GetMapping("/")
    public String home(Model model) {
        model.addAttribute("name", "Dan"); // sending name parameter to jte
        return "index";
    }
}

Properties available for JTE

# determine the jte template locations
gg.jte.templateLocation=src/main/jte # default is same

# configure template suffix
gg.jte.templateSuffix=.jte # default is same

# precompile the templates for faster startup and rendering, recommended in prod
gg.jte.usePrecompiledTemplates=true #dafault is false

# used for development as watcher will watch for changes in templates and recompile them
gg.jte.developmentMode=true

Template Syntax

${}

  • To display data from variable , can be used with general data types along with Any class implementing gg.jte.Content

<%-- ... --%>

  • To display comments

@import

  • Used to import direcly from app like classes, records etc.

  • Need to use fully qualified name e.g. @import com.app.Sample

@Param

  • It used to declare the parameter that is passed to this template. e.g. @param Sample sample

  • The datatype could be premitive or the custom dto , models or records etc.

  • For any classes we need to either import them first or need to use fully qualified name with @param.

  • we can also assign default values

@if/@endif

  • Used for flow control in the template

  • for nesting we can also use @elseif

@for and @endfor

  • Used to loop over variable

  • loop can be both fori or for in

  • we can also use @else with for , as in case of no data else part will get executed.

!{}

  • used to declare local variable

  • that can be used with ${}

Content

  • gg.jte.Content is a special parameter type, that is used to pass template code to other templates, much like lambdas in Java.

  • They are handy for sharing structures between different templates.

Example -

@import org.example.Page  # imports custom class
@import gg.jte.Content # imports content
@import my.Model

@param Page page
@param Content content
@param Content footer = null # asigning default value
@param String param;
@param Model model
@param Task task

<title>${param}</title>
<head>
    @if(page.getDescription() != null)
        <meta name="description" content="${page.getDescription()}">
    @endif
    <title>${page.getTitle()}</title>
</head>
<body>
    <h1>${page.getTitle()}</h1>
    
    <%-- if else --%>
    @if(model.entries.isEmpty())
        <p>I have no entries!</p>
    @elseif(model.entries.size() == 1)
        <p>I have one entry!</p>
    @else
        <p>I have ${model.entries.size()} entries!</p>
    @endif
    
    ## looping
    @for(var entry : model.entries)
    <li>${entry.title}</li>
    @endfor
    
    @for(int i = 0; i < 10; ++i)
        <li>i is ${i}</li>
    @endfor
    
    ## variable
    !{var innerObject = someObject.get().very().deeply().located().internal().object();}
    
    ${innerObject.a()}
    ${innerObject.b()}
    
    <div class="content">
        ${content}
    </div>
    @if (footer != null)
        <div class="footer">
            ${footer}
        </div>
    @endif
    
    <%-- importing other templte --%>
     @for(Task task : tasks)
          @template.task-row(task = task)
    @endfor
                    
</body>
task-row.jte

@import com.app.model.Task
@param Task task

<tr id="task-${task.getId()}">
    <td class="py-2">${task.getDescription()}</td>
    <td class="text-right">
        <button class="px-2 py-1 bg-red-500 text-white rounded hover:bg-red-600">
            Delete
        </button>
    </td>
</tr>

example for content -

@import org.example.WelcomePage
@param WelcomePage welcomePage

@template.layout.page(
    page = welcomePage,
    content = @`
        <p>Welcome, ${welcomePage.getUserName()}.</p>
    `,
    footer = @`
        <p>Thanks for visiting, come again soon!</p>
    `
)

Last updated