
Type-safe Java Mustache templating engine with compile-time template validation, static value binding, and extensible escaping for HTML and other content types.
A type-safe Java Mustache templating engine.
Templates are compiled into readable Java source code and value bindings are statically checked.
The doc is also on javadoc.io but is not aggregated like the above.
The aggregated javadoc is the preferred documentation and the rest of this readme
is mainly for propaganda marketing purposes.
For previous releases:
https://jstach.io/doc/jstachio/VERSION/apidocs
Where VERSION is the version you want.
Covered in why_jstachio_is_better.md.
Logicless Mustache (v 1.3) syntax.
Get JEP 430 like support today but wth even more power.
Templates are compiled into Java code
Value bindings are statically checked.
Methods, fields and getter-methods can be referenced in templates.
Friendly error messages with context.
Zero configuration. No plugins or tweaks are required. Everything is done with standard javac with any IDE and/or build-system.
Non-HTML templates are supported. Set of supported escaping content types is extensible.
Layouts are supported via the Mustache inheritance spec.
Fallback render service extension point via ServiceLoader
Customize allowed types that can be outputted otherwise compiler error (to avoid toString on classes that do not have a friendly toString).
Formatter for custom toString of variables at runtime
Add extra implements interfaces to generated code for trait like add ons (@JStacheInterfaces)
Powerful Lambda support
Map<String, ?> support
Optional<?> support
Compatible with JMustache and Handlebars list index extensions (like -first, -last, -index)
It is by far the fastest Java Mustache-like template engine as well one of the fastest in general.
Zero dependencies other than JStachio itself
An absolutely zero runtime dependency option is avaialable (as in all the code needed is generated and not even jstachio is needed during runtime). No need to use Maven shade for annotation processors and other zero dep projects. Also useful for Graal VM native projects for as minimal footprint as possible.
First class support for Spring Framework (as in the project itself will provide plugins as opposed to an aux project)
It is not a goal of this project to be the fastest java templating engine!
(however it is currently the fastest that I know when this readme was last updated)
Not that peformance matters much with templating languges (it is rarely the bottleneck) but JStachio is very fast:
https://github.com/agentgt/template-benchmark


@JStache(template = """
{{#people}}
{{message}} {{name}}! You are {{#ageInfo}}{{age}}{{/ageInfo}} years old!
{{#-last}}
That is all for now!
{{/-last}}
{{/people}}
""")
public record HelloWorld(String message, List<Person> people) implements AgeLambdaSupport {
}
public record Person(String name, LocalDate birthday) {
}
public record AgeInfo(long age, String date) {
}
public interface AgeLambdaSupport {
@JStacheLambda
default AgeInfo ageInfo(Person person) {
long age = ChronoUnit.YEARS.between(person.birthday(), LocalDate.now());
String date = person.birthday().format(DateTimeFormatter.ISO_DATE);
return new AgeInfo(age, date);
}
}
@Test
public void testPerson() throws Exception {
Person rick = new Person("Rick", LocalDate.now().minusYears(70));
Person morty = new Person("Morty", LocalDate.now().minusYears(14));
Person beth = new Person("Beth", LocalDate.now().minusYears(35));
Person jerry = new Person("Jerry", LocalDate.now().minusYears(35));
String actual = JStachio.render(new HelloWorld("Hello alien", List.of(rick, morty, beth, jerry)));
String expected = """
Hello alien Rick! You are 70 years old!
Hello alien Morty! You are 14 years old!
Hello alien Beth! You are 35 years old!
Hello alien Jerry! You are 35 years old!
That is all for now!
""";
assertEquals(expected, actual);
}
<properties>
<io.jstach.version>0.6.0-SNAPSHOT</io.jstach.version>
</properties>
...
<dependencies>
<dependency>
<groupId>io.jstach</groupId>
<artifactId>jstachio</artifactId>
<version>${io.jstach.version}</version>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source> <!-- 17 is the minimum -->
<target>17</target> <!-- 17 is the minimum -->
<annotationProcessorPaths>
<path>
<groupId>io.jstach</groupId>
<artifactId>jstachio-apt</artifactId>
<version>${io.jstach.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
N.B. The annotations jar (jstachio-annotation) is pulled in transitively
dependencies {
implementation 'io.jstach:jstachio:VERSION'
annotationProcessor 'io.jstach:jstachio-apt:VERSION'
}
{{#name}}
<p>Name: {{.}}, Name Length is {{length}}</p>
{{/name}}
<p>Age: {{ age }}</p>
<p>Achievements:</p>
<ul>
{{#array}}
<li>{{.}}</li>
{{/array}}
</ul>
{{^array}}
<p>No achievements</p>
{{/array}}
<p>Items:</p>
<ol>
{{#list1}}
<li>{{value}}</li>
{{/list1}}
</ol>
Following class can be used to provide actual data to fill into above template.
@JStache(
// points to src/main/resources/user.mustache file
path = "user.mustache",
// or alternatively you can inline the template
template = "",