Java 8 optimized, memory efficient, speedy template engine producing statically typed, plain java objects

Overview

Rocker Templates by Fizzed

Build Status Maven Central

Fizzed, Inc. (Follow on Twitter: @fizzed_inc)

Sponsored by

Rocker is proudly sponsored by Greenback. We love the service and think you would too.

Greenback

More engineering. Less paperwork. Expenses made simple.

Overview

Rocker is a Java 8 optimized (runtime compat with 6+), near zero-copy rendering, speedy template engine that produces statically typed, plain java object templates that are compiled along with the rest of your project. No more "warm-up" time in production, slow reflection-based logic, or nasty surprises that should have been caught during development.

Write your templates using an intuitive, tagless syntax with standard Java expressions for logic, iteration, and values. Use Rocker's special ? presence operator for null-safe evaluation. All the heavy lifting is done by the Rocker parser during development -- which keeps the runtime dependencies down to just a handful of classes. Rocker will parse your templates and generate well-documented Java source files (so you can easily inspect and understand how it works).

Performance

Based on the following template benchmark, Rocker is the clear winner. ~250% faster than Freemarker while also requiring orders-of-magnitude less memory.

Template Comparison

Two-minute drill

Most templates are used for websites, so here is a quick sample showing how Rocker templates work and can call each other during the rendering process. Create a template containing a common header and footer as well as a placeholder for body content. Create template src/main/java/views/main.rocker.html

@args (String title, RockerBody content)

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

The template we actually plan on showing to a user will render its content within the context of the common/header footer. In Java terms, it's passing a block of rendering code to be executed within another template. Create template src/main/java/views/index.rocker.html

@args (String message)

@views.main.template("Home") -> {
    <h1>Hello @message!</h1>
}

Hey, what about the RockerBody content argument? We cover it in more detail in the syntax readme, but for now just understand that its the only special type of argument and instructs Rocker that a template expects a "body" to be passed to it.

The Rocker parser will generate a Java source file for each template. They will be target/generated-sources/rocker/views/main.java and target/generated-sources/rocker/views/index.java. In your application, you can render the index template like so.

static public void main(String[] args) {

    String output = views.index.template("World")
        .render()
        .toString();

}

The output will equal:

<html>
    <head>
        <title>Home</title>
    </head>
    <body>
        <h1>Hello World!</h1>
    </body>
</html>

Once you generate the Java sources and peek inside the code, it's simple to see how this works. The views.index class creates a views.main template instance and hands off rendering to it -- while also passing a block of itself that it will render when views.main calls the @content variable. The syntax is identical to how a lambda is defined in Java 8 (implemented with lambdas for Java 8 and anonymous inner classes for Java 6/7). Rocker does a number of things behind the scenes to make sure templates that create other templates share the same rendering context (output buffer, application-specific context/implicit state).

Features

  • Templates are runtime compatible with Java 6+

  • Optimizations enabled when targeting Java 8+ -- using Lambdas and type inference under-the-hood

  • Near zero-copy rendering

  • Hot reload support in two flavors

  • Elegant, intuitive, tagless syntax that infers when your logic ends for control / dynamic content. All dynamic / control code uses standard Java syntax.

  • A special ? presence operator extends syntax for simplified handling of null values.

  • Parsed templates become normal POJOs with defined arguments -- allowing you to tap into your IDEs code completion, syntax highlighting, etc.

  • Support for injecting intermediate application-specific super classes during parsing & generating phase -- thereby creating your own app-specific template engine where you can make implicit variables/methods available to all templates.

  • Since templates are just Java classes -- your logic / dynamic content can call out to any other Java code. Your templates can be as advanced or as simple as you need. No reflection used.

  • No runtime configuration/engine required -- there isn't any sort of RockerEngine class required to execute templates. Each compiled template is ready-to-go and knows how to render itself.

  • Templates retain enough information about the original template to throw exceptions at runtime (during render()) that let you track down the problematic line in the original template source file.

Syntax

Checkout the SYNTAX.md file for a comprehensive deep dive on the rocker syntax.

Framework integrations

Rocker has a growing list of frameworks that it has been seamlessly integrated with. If you want to link to a new framework added, please file an issue or submit a PR:

Near zero-copy rendering

Static (plain text) for each Rocker template is (by default) stored internally as static byte arrays already converted into your target charset (e.g. UTF-8). When a template is rendered -- the static byte arrays are reused across all requests. Rocker renders to an optimized output stream that stores a composite (linked list) view of the reused byte arrays plus your dynamic content. Since templates consist mostly of static content rendered into the same charset over and over again, rather than allocating new memory, copying that content, and then converting it into your target charset for each request -- Rocker simply uses a pointer to it over and over again. This technique produces fast and memory efficient renders.

Let's say you have a template consisting of 9000 bytes of plain static text and 1000 bytes of dynamic content. Without this optimization, it would require ~100MB of memory to service 10000 requests (10000 bytes x 10000 requests). With this optimization, it would require ~10MB of memory to service 10000 requests (1000 bytes x 10000 requests). Besides lower memory, you also cut out 90MB of memory copies and 90MB of UTF-8 String->byte conversions. A pretty useful optimization.

No reflection

Everything is compiled by your project's compiler along with your other Java source code. Any dynamic code in your template is ultimately converted into standard Java and compiled. No reflection used.

Hot reloading

Version 0.10.0 introduced support for hot reloading templates during development. Hot reloading allows you to modify the template source code, save it, and have the changes active on the next request -- without having to restart your JVM. Rocker offers two different flavors of hot reloading for flexibility.

Flavor 1: static interface, dynamic rendering

The major feature of Rocker templates is that your templates are compile-time checked for usage, arguments, logic, etc. by the Java compiler.

In version 0.10.0 the underlying structure of a template was modified where a template generates two underlying classes. Each template generates a model class (its interface) and an implementation class (its renderer). Your application will only interact directly with the model, therefore allowing Rocker to dynamically recompile and reload the implementation class.

The major benefit of flavor one is that your application code remains the same and is compile-time checked by the Java compiler, while the template content can be modified and automatically reloaded at runtime. Only in the case where you actually change the template arguments, will you need to restart your application.

Flavor 2: dynamic interface, dynamic rendering

If you prefer the convenience of fully dynamic templates, flavor two supports hot reloading of both the template model class (its interface) as well as the implementation class (its renderer). Your application will lose some of the compile-time checking and a small performance hit, but gain the convenience of everything being reloadable. The way your application will use templates is different as well.

import com.fizzed.rocker.Rocker

...

// dynamic interfaces, dynamic implementation
String rendered = Rocker.template("views/index.rocker.html")
    .bind("val", "ValueA")
    .render()
    .toString();

The template path and arguments will be runtime-checked. Please note that each bindable value must match the name and type declared in your template.

In case your bindable map may contain more values that than the required ones a relaxed bind is available. The relaxed alternative will not fail rendering if an attribute is extra to the required list. For example:

@args (String name)
Hello ${name}!

Will render in relaxed mode as:

Map map = new HashMap();
map.put("name", "Joe");
map.put("age", 42);

Rocker.template("views/hello.rocker.html")
    .relaxedBind(map)
    .render();
// -> Hello Joe!

Activate hot reloading

Support for hot reloading is added to your generated templates by default in version 0.10.0. If you'd like to disable support, set the configuration/system property rocker.optimize to true during your build. Since the code is present in your templates by default, you merely need to turn it on at runtime.

Add dependency

The rocker-compiler dependency needs to be added to your build. This dependency only needs to be present during development and can be removed in production. In Maven, this means you'll want to add the dependency in the provided scope.

<dependency>
    <groupId>com.fizzed</groupId>
    <artifactId>rocker-compiler</artifactId>
    <version>1.3.0</version>
    <scope>provided</scope>
</dependency>

Enable at runtime

Activate hot reloading at runtime. You can activate hot reloading either with a system property or programmatically. For activating hot reloading with a system property in maven.

mvn -Drocker.reloading=true ...rest of args...

Alternatively, you can activate hot reloading programmatically.

import com.fizzed.rocker.runtime.RockerRuntime

...

RockerRuntime.getInstance().setReloading(true);

Try out hot reloading

There is a simple example demonstrating hot reload in action. This project uses Blaze to help script tasks. Run the following

java -jar blaze.jar hot_reload

Point your browser to http://localhost:8080

Then modify & save rocker-test-reload/src/test/java/views/index.rocker.html and refresh your browser.

Getting started

Rocker consists of two components - the parser/generator and the runtime. To use Rocker in your project, add the runtime dependency to your application, then enable the parser in your build tool followed by creating your first template.

Add dependency

Rocker is published to Maven central. To add as a dependency in Maven:

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

<!-- for hot-reloading support only during development -->
<dependency>
    <groupId>com.fizzed</groupId>
    <artifactId>rocker-compiler</artifactId>
    <version>1.3.0</version>
    <scope>provided</scope>
</dependency>

To add as a dependency in Gradle:

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'com.fizzed', name: 'rocker-runtime', version: '1.3.0'
    // add rocker-compiler dependency as needed
}

Integrate parser/generator in build tool

Rocker supports Maven and Gradle out-of-the box.

Maven

Add the following to your pom

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

By default, Rocker will recursively process any template files ending with .rocker.html in src/main/java. The directory the template is saved will become the standard Java package the generated Java classes will be placed into. The generated Java source files will be saved to target/generated-sources/rocker. The plugin will take care of adding this generated directory to your sources root.

The following properties are supported:

  • templateDirectory is the base directory to recursively start from when locating and parsing template files. The Java package a template will be generated to will use this directory as its base. So if you have ${templateDirectory}/views/mytemplate.rocker.html then Rocker will generate ${outputDirectory}/views/mytemplate.java. Defaults to ${project.build.sourceDirectory}.

  • outputDirectory is the directory the parser will generate sources for templates. Defaults to ${project.build.directory}/generated-sources/rocker

  • classDirectory is the directory the hot reload feature will (re)compile classes to at runtime. Defaults to ${project.build.outputDirectory}

  • failOnError determines whether any parsing/generating errors cause Maven to fail. Defaults to true.

  • skip determines whether execution of the plugin should be skipped. Defaults to false.

  • touchFile is the file to "touch" after successfully generating Java sources. Useful for triggering other workflow. Many IDEs will not automatically reload generated sources for code completion unless either explicitly told to reload OR if the maven pom.xml file is changed. Thus, this value is by default set to ${basedir}/pom.xml. It's usually harmless to keep this enabled.

  • skipTouch disables touchFile. Defaults to false.

  • addAsSources will add the outputDirectory to maven as sources to be compiled. Defaults to true.

  • addAsTestSources will adds the outputDirectory to maven as test sources to be compiled. Defaults to false. If true, this is evaluated before addAsSources and effectively tells maven to compile your templates as test code.

The following properties are also supported, but it's important to understand these are essentially passthrough overrides to the parser and they all default to Rocker's default value.

  • javaVersion is the Java version you'd like your templates compile & runtime compatible with. Defaults to the Java version of the JVM executing maven (e.g. "1.8").

  • optimize determines if hot reloading support will be removed from the generated templates. False by default.

  • extendsClass is the class that all template implementations should extend. Useful for application-specific intermediate classes that you'd like all templates to extend. Defaults to Rocker's default.

  • extendsModelClass is the class that all template models should extend. Useful for application-specific intermediate classes that you'd like all template models to extend. Defaults to Rocker's default.

  • discardLogicWhitespace determines whether whitespace in templates that is determined to be only a part of logic/control blocks should be discarded. Helps make rendered content look more professional, while still keeping much of your formatting intact. Defaults to Rocker's default.

  • targetCharset is the target charset for template output. Defaults to Rocker's default.

  • suffixRegex is the regular expression to use to find templates to parse. Defaults to Rocker's default.

  • markAsGenerated adds a @Generated annotation to the generated classes. The Retention is CLASS so that the annotation can be used by tools that only rely on the class files and not on the source code. Defaults to Rocker's default.

Gradle

Thanks to @victory and @mnlipp for contributing the gradle plugin. @etiennestuder also had an alternative Gradle plugin you may want to consider as well. Rocker's gradle plugin is published to gradle.org. Just add the following to your build script:

plugins {
  id "com.fizzed.rocker" version "1.3.0"
}

sourceSets {
    main {
        rocker {
            srcDir('src/main/java')
        }
    }
}

rocker {
    // (All settings are shown with their defaults)
    // 
    // Skips building templates all together
    skip false
    // Base directory for generated java sources, actual target is sub directory 
    // with the name of the source set. The value is passed through project.file(). 
    outputBaseDirectory = "$buildDir/generated-src/rocker"
    // Base directory for the directory where the hot reload feature 
    // will (re)compile classes to at runtime (and where `rocker-compiler.conf`
    // is generated, which is used by RockerRuntime.getInstance().setReloading(true)).
    // The actual target is a sub directory with the name of the source set. 
    // The value is passed through project.file().
    classBaseDirectory = "$buildDir/classes"
    failOnError true
    skipTouch true
    // must not be empty when skipTouch is equal to false
    touchFile ""
    javaVersion '1.8'
    extendsClass null
    extendsModelClass null
    optimize null
    discardLogicWhitespace null
    targetCharset null
    suffixRegex null
    postProcessing null
    markAsGenerated null
}

Create first template

The template syntax is described in detail below, but for now create a new file in ${templateDirectory}/views/HelloWorld.rocker.html

@*
 Example of hello world
*@
@args (String message)

Hello @message!

Use compiled template

Time to compile your project and starting using the template. You can call it from java like so:

static public void main(String[] args) {

    String output = views.HelloWorld
        .template("World")
        .render()
        .toString();

}

Use optimized output

Rocker is heavily optimized (by default) to output templates as byte arrays. The default RockerOutput a template will render to is of the type com.fizzed.rocker.runtime.ArrayOfByteArraysOutput. This is an excellent choice for byte arrays or asynchronous IO. However, the framework has the capability for optimized rendering to Strings (or other custom outputs).

To efficiently render to a String:

import com.fizzed.rocker.runtime.StringBuilderOutput;

static public void main(String[] args) {

    StringBuilderOutput output = views.HelloWorld
        .template("World")
        .render(StringBuilderOutput.FACTORY);

    String text = output.toString();

}

To efficiently render to an OutputStream:

import com.fizzed.rocker.runtime.OutputStreamOutput;

static public void main(String[] args) throws Exception {

    final OutputStream os = new FileOutputStream(new File("test"));

    OutputStreamOutput output = views.HelloWorld
        .template("World")
        .render((contentType, charsetName) -> new OutputStreamOutput(contentType, os, charsetName));

}

Please note that if there is an exception during the render the OutputStream would have a partial template rendered (up to the point of the exception). In most cases it would be better to render to the default com.fizzed.rocker.runtime.ArrayOfByteArraysOutput and write its buffer of byte arrays out directly to your OutputStream.

Other demos?

There are numerous demos of Rocker in action. From parsing templates into a model to asynchronously sending results in an HTTP server. This project uses Blaze to help script tasks. Run the following for a complete list:

java -jar blaze.jar -l

License

Copyright (C) 2015 Fizzed, Inc.

This work is licensed under the Apache License, Version 2.0. See LICENSE for details.

Comments
  • Rocker gradle plugin

    Rocker gradle plugin

    I have added a rocker gradle plugin. The README.md in the rocker-gradle-plugin directory should explain how to use it. This in response to issue #33.

    It currently exports to a local maven repo to be consumed by local projects, however it would be nice if it was shared on Maven Central.

    I am sure there will be questions and I would be happy to answer them.

    opened by Victory 19
  • Great work

    Great work

    Hello, I'm using ninja framwork with rythm engine

    I'm a big fan of .net razor syntax, as it is clear and short and very easy to use. I'm using rythm engine as it is quite the same as razor.

    I'm very interested in rocker, except for one thing, I definitely can't miss the hot reloading feature. I understand why you didn't made it, but I'm convinced that this is a must have, especially for our designers.

    I'm not an expert in this domain, but I believe that even if the class loader and compile coding is horrible inside rythm code, they have found a good way to do it.

    The big plus of your approach, is that everything is compiled into a strongly typed class, which is a very good point.

    Maybe a good way to implement hot reloading is to break the strongly typed access to views in the controllers, and fall back to something more classic like.

    What I try to mean is that there will be no strong reference to the generated rocker classes from the application, but only in the other way. This allowing to compile generated java classes without recompiling the whole project, which makes UI developping much much faster...

    Well I'm sure you understand what I try to (hardly) explain...

    Any way, goog work, keep on going !

    Note: not everything in rythm is interesting and should be ported, but I think some of them can be usefull, like master pages (I mean the use of @section and @render), and the ability to create functions (see @def, looks like it is the same as calling another template, but with @def one can put all functions in the same file).

    If you're interested, I can have a closer look to rythm which I use every day to determine the must have items missing in rocker - I'm sure it's only a very small number of them.

    Whatever you decide, bravo

    enhancement 
    opened by momiji 15
  • Discarding whitespace from templates

    Discarding whitespace from templates

    Hi,

    when creating HTML templates, I'm using indentation, empty lines, etc. quite generously to help with the readability during development. However, such is not needed (and unnecessarily blows up the resulting page) in production.

    What would be nice is if Rocker could be configured (comparable to the "discardLogicWhitespace" option) to automatically discard all (or some) whitespace, including but not necessarily limited to,

    • empty lines
    • spaces and/or tabs at the beginning and end of every line
    • sets of more than one space/tab within lines

    One simple approach would be to simply add code for this into PlainText.unescape(), but at least for the items above special cases such as "pre" elements or "CDATA" sections should probably not receive such treatment and would have to be parsed separately. There might be other cases where the original strings should be left unaltered which I can't think of right now. Also, for non-HTML templates this might be an issue, but then again it should probably be configurable on/off on a per-template basis anyway.

    What do you think? Or is there any other (preferable) solution to this in your opinion? (I'm using Rocker within Ninja applications, but I don't think messing with the Result renderables there would be the right approach either.)

    opened by jfendler 14
  • Mark generated classes as generated #116

    Mark generated classes as generated #116

    @jjlauer this is my initial attempt at #116.

    I haven't made the feature configurable yet, because there is something I want to discuss first.

    My intention was to apply the annotation to every class rocker generates. The catch is, that rocker generates:

    • anonymous classes for java 6 and 7
    • lambas for java 8

    Right now java does not allow annotations on either of them.

    For anonymous classes there might be a solution in the form of JSR308 (Introduced in java 8).

    callMethod(new @Generated AnonymousClass(){})
    

    But this also has it's problems:

    1. I don't think JaCoCo supports JSR308 annotations.
    2. This only works for anonymous classes. Those are only generated by rocker on the <8 java profile. But JSR308 requires at least java 8.

    Those are the options we have in the order my preference:

    0: Promote the anonymous classes and lambdas to proper classes Let's generate the problematic classes as static inner classes that can be annotated.

    Pros:

    • Only rocker code changes required.
    • Completely solves the problem. JaCoCo works now.

    Cons:

    • This is a rather big change.

    1: Ask JaCoCo to change We/I can ask JaCoCO to change their logic. They should ignore anonymous classes or lambdas inside of classes marked as @Generated.

    Pros:

    • The rocker changes are kept minimal.
    • Seems like the right thing to me.

    Cons:

    • Bigger coordination effort since 2 projects are now affected.

    2: Abandon the idea Let's do nothing and chill.

    Pros:

    • Still better than 3 imo.

    Cons:

    • My problem is not solved :(

    3: Use JSR308 annotations For java8 let's use JSR308 annotations. Remove the lambdas and replace them with anonymous classes.

    Pros:

    • ?

    Cons:

    • Changes in JaCoCo required.
    • Only works for java >8.
    • Combines the disadvantage of a big change as in 0, with none of it's advantages.
    opened by Serranya 10
  • Implement support for rendering to InputStreamRockerOutput

    Implement support for rendering to InputStreamRockerOutput

    Hello everyone,

    I use rocker to render "into" an InputStream which can be consumed later. I would like to have this feature included in the offical rocker distribution to make reuse simpler and share with the community.

    opened by Serranya 10
  • Static info in compiled templates break Gradle incremental compiler

    Static info in compiled templates break Gradle incremental compiler

    In our project we make use of rocker rely on incremental compilation within our project. Compiled rocker templates result in a classes with multiple public constants. Incremental compilation is disabled as soon as a class with public constants have changed. Do you consider to replace these constants in the classes with static methods? That would a) fix the incremental compile behavior when changing rocker templates and b) seem also be more appropriate as these fields seems not be really constant (as constant as e.g. PI) but based on certain inputs.
    the related issue in gradle (including an reproducable example) and the discussion around this in the gradle build tool team can be found at https://github.com/gradle/gradle/issues/6482

    opened by breskeby 10
  • Render final keyword for @for loops in java source or source may not compile

    Render final keyword for @for loops in java source or source may not compile

    Hi there,

    I have been using Rocker for our new development project as I accidentally found it and like the concepts. Unfortunately I ran into the following issue while trying it out, see the sample code below.

    @for (ModelClass modelClass : modelClasses) { @with (List<Method> methodsFound = modelClass.getMethods()) { @if (!methodsFound.isEmpty()) { // Class: @modelClass.getFullyQualifiedName() } } } The line Class: @modelClass.getFullyQualifiedName() will not compile, because modelClass is rendered as non-final variable in the template java source (java compiler message: "Cannot refer to the non-final local variable modelClass defined in an enclosing scope").

    Afaict the easiest way to deal with this is render these assignments with the final keyword always, that would apply to anything where things are assigned like in the different @for loops (and possibly more?).

    The above or e.g. class ForStatement needs to deal with an optional 'final' keyword (and probably more different statements).

    I am happy to help you fix this, if you tell me what solution you prefer (I know antlr4 quite well too). But only if you want me to do so. If so, I'll make a pull request then.

    I hope you can help out as it's blocking our progress.

    opened by mreuvers 10
  • Enhance @with by supporting multiple arguments

    Enhance @with by supporting multiple arguments

    Hey Joe,

    As said, this is a useful enhancement. I intend to add this (creating this issue to track). It will look like this:

    @with (String s=list.get(0), List<Long> list=x.getIt()) {
     ...
    }
    

    And an equivalent java 8 version. The change will be backwards compatible, so the single argument switch will remains working as is.

    There is however one thing I am not sure about, the null-safe with statement. If multiple arguments are present, and the with statement is tagged with '?'. What shall we do:

    • Execute the block inside, if all the arguments are non-null
    • Forbid the null-safe with if there's more than 1 argument
    • ...

    Example:

    @with? (String s=list.get(0), List<Long> list=x.getIt()) {
     ..
    }
    else {
    
    }
    

    What are your thoughts?

    opened by mreuvers 9
  • Make @for work with any Iterable object

    Make @for work with any Iterable object

    This change makes the rocker @for syntax match the java syntax by accepting any object implementing Iterable.

    I've added this as a workaround for the @for syntax not working with streams (see #40) (passing stream::iterator to the template instead of collecting to a list - and thus saving my server from high memory usage), but I'm sure others will appreciate not requiring a Collection when all that's used is the Iterable interface.

    opened by bendem 8
  • Compiled classes have missing package declaration.

    Compiled classes have missing package declaration.

    Compiled templates create java files that lacks the package declaration on the first line, this causes issues on several IDE's and compile environments.

    At least a property to enable package inclusion/exclusion should be added to fit all project needs.

    // <-- Package with the same path as outputDirectory should go here!!!
    
    import java.io.IOException;
    import com.fizzed.rocker.ForIterator;
    import com.fizzed.rocker.RenderingException;
    import com.fizzed.rocker.RockerContent;
    import com.fizzed.rocker.RockerOutput;
    import com.fizzed.rocker.runtime.DefaultRockerTemplate;
    import com.fizzed.rocker.runtime.PlainTextUnloadedClassLoader;
    
    /*
     * Auto generated code to render template /TestTempalte.rocker.html
     * Do not edit this file. Changes will eventually be overwritten by Rocker parser!
     */
    public class TestTempalte extends com.fizzed.rocker.runtime.DefaultRockerModel {
    
    ...
    
    opened by lethevimlet 8
  • Suggestion: allow accessing parameter names

    Suggestion: allow accessing parameter names

    It would be nice to have this API made public:

    https://github.com/fizzed/rocker/blob/master/rocker-runtime/src/main/java/com/fizzed/rocker/Rocker.java#L72

    The use case:

    You have a generic template and allow users to pass you a generic map with all possible variables.

    If the variables do not match the template arguments you'll get an error. Sometimes variables do not match because the user passed some extra values, imagine a map that gets enriched as it is processed by the user API.

    Having a way to know the expected arguments, we could bind the required arguments only ignoring the extras and making the template always to succeed.

    opened by pmlopes 7
  • Bump undertow-core from 1.3.18.Final to 2.2.19.Final

    Bump undertow-core from 1.3.18.Final to 2.2.19.Final

    Bumps undertow-core from 1.3.18.Final to 2.2.19.Final.

    Commits
    • 2ec4d95 Prepare 2.2.19.Final
    • e52cefb Merge pull request #1361 from fl4via/2.2.x_backport_bug_fixes
    • 215316d [UNDERTOW-1997] Add test for a security constraint with "/" path URL Pattern
    • e2b1e68 [UNDERTOW-1997] Corrected handling of security constraints with URL pattern '/'
    • e8ae803 [UNDERTOW-1934] invoke onClose in case of network failure
    • 6f620cd [UNDERTOW-2125] At ReadTimeoutStreamSourceConduit, skip expiration if connect...
    • 9a06b56 Merge pull request #1353 from kstekovi/UNDERTOW-2112_2.2.x
    • 5177c78 Merge pull request #1359 from fl4via/2.2.x_backport_bug_fixes
    • 1d95f77 [UNDERTOW-2135] Partial revert of hack from commit id: 55445de
    • 7d3a045 [UNDERTOW-2133] Handle RequestTooBigException
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Global default null value rendering to avoid NPEs

    Global default null value rendering to avoid NPEs

    Hi Rocker !

    Is there a way to provide default value for null to avoid NPE during rendering, for example rendering empty string instead ?

    I understand there's a null-safety operator, but considering there are lots of variables to render in a lot of pages, this could become cumbersome.

    Thank you !

    opened by albert-kam 0
  • Generation crashes with NPE if a non-normal file is present in the template directory

    Generation crashes with NPE if a non-normal file is present in the template directory

    The method RockerUtil.listFileTree throws a NullPointerException if there is any file within the template directory which is neither a "normal file" (as defined by File.isFile()) nor a directory.

    In my special case, I had a broken symlink in there, but I think other special files might also trigger this. Fixes which I can think of:

    1. check with else if (entry.isDirectory()), so that special files are ignored and only actual directories are passed to the recursive method call
    2. surround the for-loop with try-catch and print the path of the offending file, so that the user can delete / fix the file
    opened by lenaschimmel 1
  • Unable to get hot-reload working with tomcat server

    Unable to get hot-reload working with tomcat server

    Hi,

    I'm unable to get hot-reload working in my application, I'm using tomcat (embedded) as server.

    When compile is called during runtime, TemplateCompiler is unable to fetch classpathUrls from TomcatEmbeddedWebappClassLoader and hence get compilation errors.

    Capture

    Can classpath be appended with whatever System.getProperty("java.class.path") returns, if classpathUrls is empty ?

    opened by JimmyWe11s 3
Releases(v0.10.3)
Owner
Fizzed, Inc.
Helping companies launch and grow their mobile, web, and data products
Fizzed, Inc.
jte is a secure and lightweight template engine for Java.

jte is a secure and lightweight template engine for Java. All jte templates are compiled to Java class files, meaning jte adds essentially zero overhe

Andreas Hager 457 Dec 22, 2022
Java modern template engine

Jtwig Project Documentation Project Status Coverage Version jtwig-reflection jtwig-core jtwig-web jtwig-pluralization jtwig-spring jtwig-translate-ext

Jtwig 298 May 19, 2022
ST (StringTemplate) is a java template engine (with ports for C#, Python, and Objective-C coming) for generating source code

ST (StringTemplate) is a java template engine (with ports for C#, Python, and Objective-C coming) for generating source code, web pages, emails, or an

Antlr Project 851 Jan 5, 2023
Multiproject template for ForgeGradle development environments

ForgeGradle Multiproject Template This repository provides a template for multiproject development environments using ForgeGradle. Project structure T

Néstor Amador 10 Jun 3, 2022
A little template project to

FX Modules This is a little project that can be used as a template for modularized JavaFX projects. The main branch is based on JDK17, other version c

Gerrit Grunwald 27 Dec 12, 2022
Pebble is a java templating engine inspired by Twig

Pebble Pebble is a java templating engine inspired by Twig. It separates itself from the crowd with its inheritance feature and its easy-to-read synta

null 985 Dec 23, 2022
a pug implementation written in Java (formerly known as jade)

Attention: jade4j is now pug4j In alignment with the javascript template engine we renamed jade4j to pug4j. You will find it under https://github.com/

neuland - Büro für Informatik 700 Oct 16, 2022
Te4j (Template Engine For Java) - Fastest and easy template engine

Te4j About the project Te4j (Template Engine For Java) - Fastest and easy template engine Pros Extremely fast (127k renders per second on 4790K) Easy

Lero4ka16 19 Nov 11, 2022
Annotation processor to create immutable objects and builders. Feels like Guava's immutable collections but for regular value objects. JSON, Jackson, Gson, JAX-RS integrations included

Read full documentation at http://immutables.org // Define abstract value type using interface, abstract class or annotation @Value.Immutable public i

Immutables 3.2k Dec 31, 2022
A Java architecture test library, to specify and assert architecture rules in plain Java

ArchUnit is a free, simple and extensible library for checking the architecture of your Java code. That is, ArchUnit can check dependencies between pa

TNG Technology Consulting GmbH 2.5k Jan 2, 2023
Behavior-Driven Development in plain Java

JGiven is a developer-friendly and pragmatic BDD tool for Java. Developers write scenarios in plain Java using a fluent, domain-specific API, JGiven g

TNG Technology Consulting GmbH 393 Dec 23, 2022
A desktop java GUI application to encrypt your plain text

A desktop java GUI application to encrypt your plain text

Nikhil Narayanan 4 Sep 10, 2022
Java port of Brainxyz's Artificial Life, a simple program to simulate primitive Artificial Life using simple rules of attraction or repulsion among atom-like particles, producing complex self-organzing life-like patterns.

ParticleSimulation simple Java port of Brainxyz's Artificial Life A simple program to simulate primitive Artificial Life using simple rules of attract

Koonts 3 Oct 5, 2022
Apache Camel is an open source integration framework that empowers you to quickly and easily integrate various systems consuming or producing data.

Apache Camel Apache Camel is a powerful, open-source integration framework based on prevalent Enterprise Integration Patterns with powerful bean integ

The Apache Software Foundation 4.7k Dec 31, 2022
Apache Camel is an open source integration framework that empowers you to quickly and easily integrate various systems consuming or producing data.

Apache Camel Apache Camel is a powerful, open-source integration framework based on prevalent Enterprise Integration Patterns with powerful bean integ

The Apache Software Foundation 4.7k Jan 8, 2023
FlatBuffers: Memory Efficient Serialization Library

FlatBuffers FlatBuffers is a cross platform serialization library architected for maximum memory efficiency. It allows you to directly access serializ

Google 19.6k Dec 31, 2022
Drools is a rule engine, DMN engine and complex event processing (CEP) engine for Java.

An open source rule engine, DMN engine and complex event processing (CEP) engine for Java™ and the JVM Platform. Drools is a business rule management

KIE (Drools, OptaPlanner and jBPM) 4.9k Dec 31, 2022