Giter VIP home page Giter VIP logo

ninja-rocker's Introduction

Ninja Framework + Rocker Templates by Fizzed

Build Status Maven Central

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

Overview

Integration of Rocker templates with the Ninja Framework. Rocker is a Java 8 optimized, 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.

This project makes Rocker templates a first-class citizen to Ninja. All Ninja-specific functionality is provided by way of the N variable that is available to all templates. Here is a quick sample of what a index.rocker.html template would look like using a few of the most common Ninja features.

@import controllers.Application

@args (String title)

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@title</title>
    <link rel='stylesheet' href='@N.webJarsAt("bootstrap/3.3.2-1/css/bootstrap.min.css")'>
    <link rel='stylesheet' href='@N.assetsAt("css/app.css")'>
</head>
<body>
    Hi!
    <a href='@N.reverseRoute(Application.class, "index")'/>Home</a>
</body>
<script type="text/javascript">
@if (N.isProd()) {
    /* production-only code (e.g. google analytics) */
}
</script>
</html>

Once compiled into your project, you can call this template from your Ninja controller. Fully type safe and compile-time checked.

public class Application {
    
    public Result index() {
        return Results.ok().render(
            views.index.template("Home")
        );
    }

}

Demo

There is a Ninja app in the demo folder that demonstrates all the functionality this module provides and it's a simple way to see how it works. This project uses Blaze to help script tasks. Run the following in your shell (from the root project directory, not in demo):

java -jar blaze.jar demo

Once running, point your browser to http://localhost:8080/

Ninja 5 (or lower) support?

Please use ninja-rocker v0.15.0 or below if you need to target an older version of Ninja.

Setup

Add dependency

Add the ninja-rocker-module dependency to your Maven pom.xml

<dependency>
    <groupId>com.fizzed</groupId>
    <artifactId>ninja-rocker-module</artifactId>
    <version>0.16.0</version>
</dependency>

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

Add module to conf/Module.java

Add the module to your conf/Module.java file. Once installed, Rocker will replace the default FreeMarker template engine for all content with the type of "text/html".

package conf;

import com.fizzed.ninja.rocker.NinjaRockerModule;
import com.google.inject.AbstractModule;

public class Module extends AbstractModule {

    @Override
    protected void configure() {
        install(new NinjaRockerModule());
    }

}

Add maven plugin

Rocker ties into Maven with a plugin to parse templates and generate the Java source during the generate-sources phase. In order to access the N variable and access Ninja features in your templates, it's critical you configure the extendsClass variable as below.

<build>
    <plugins>
        <plugin>
            <groupId>com.fizzed</groupId>
            <artifactId>rocker-maven-plugin</artifactId>
            <version>0.15.0</version>
            <executions>
                <execution>
                    <id>generate-rocker-templates</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <extendsClass>com.fizzed.ninja.rocker.NinjaRockerTemplate</extendsClass>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

For more detailed information on Rocker and its maven plugin, please visit the Rocker project site.

Exclude rocker templates as a resource

Ninja recommends including everything except .java files from src/main/java by default. Since Rocker's templates are compiled, this isn't necessary and you can safely exclude Rocker templates from your final build.

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*</include>
            </includes>
            <!-- add rocker template exclude below -->
            <excludes>
                <exclude>**/*.java</exclude>
                <exclude>**/*.rocker.html</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*</include>
            </includes>
        </resource>
    </resources>
</build>

Exclude rocker compiled templates from triggering Ninja SuperDevMode restart

By default, Ninja's SuperDevMode watches all .class files in your target/classes directory. Any modification to the contents of that directory will trigger the Ninja HTTP server to restart. Rocker's templates are compiled and with hot reload enabled, Rocker will recompile and reload your templates without requiring a JVM restart. Unfortunately, Ninja's defaults will still trigger a restart since Rocker will recompile and change the contents of target/classes. As long as you stick to the convention that any class in the views package is a rocker template, you can exclude these classes:

<build>
    <plugins>
        <plugin>
            <groupId>org.ninjaframework</groupId>
            <artifactId>ninja-maven-plugin</artifactId>
            <version>6.0.0-beta2</version>
            <configuration>
                <useDefaultExcludes>true</useDefaultExcludes>
                <excludes>
                    <exclude>(.*)rocker.html$</exclude>
                    <exclude>(.*)views/(.*).class$</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

Write templates

It's best to place your templates in the views folder of your application with a suffix of .rocker.html.

Ninja variable

Easiest way to discover all the properties and methods available in the N variable is to take a look at NinjaRocker.java.

Application-specific templates

Looking for the ultimate integration of Ninja into your application? Create your own application-specific template that subclasses NinjaRockerTemplate and expose any number of useful variables and/or methods to any of your templates.

The demo has an example of how to do it here.

Write your own application-specific template

Create a new class called utils.ApplicationRockerTemplate. This class will subclass com.fizzed.ninja.rocker.NinjaRockerTemplate and then it will need to override two methods to participate in the rendering process.

package utils;

import com.fizzed.ninja.rocker.DefaultNinjaRocker;
import com.fizzed.ninja.rocker.NinjaRockerTemplate;
import com.fizzed.rocker.RockerModel;
import com.fizzed.rocker.RockerTemplate;
import com.fizzed.rocker.RockerUtils;

abstract public class ApplicationRockerTemplate extends NinjaRockerTemplate {

    public ApplicationRocker A;
    
    public ApplicationRockerTemplate(RockerModel model) {
        super(model);
    }
    
    /**
     * Apply NinjaRocker to template immediately before rendering. Best place
     * to setup your own application-specific properties or methods that rely
     * on Ninja context, router, messages, etc.
     * @param N The ninja rocker instance
     */
    @Override
    public void __apply(DefaultNinjaRocker N) {
        super.__apply(N);
        this.A = new ApplicationRocker(N);
    }

    /**
     * Associate this template with another template during the rendering
     * process.  This occurs when Template A calls or includes Template B.
     * Usually, you simply want to copy over the variables you created in
     * the __apply method.
     * @param template The template to associate us with
     */
    @Override
    protected void __associate(RockerTemplate template) {
        super.__associate(template);
        ApplicationRockerTemplate applicationTemplate
            = RockerUtils.requireTemplateClass(template, ApplicationRockerTemplate.class);
        this.A = applicationTemplate.A;
    }
    
}

(demo/src/main/java/utils/ApplicationRockerTemplate.java) (demo/src/main/java/utils/ApplicationRocker.java)

Use your own A variable

In this example, we are exposing the ApplicationRocker class as a variable named A. In your template, you can then access it like so

<h1>@A.user.getName()</h1>

The possibilities are obviously endless -- and remember that the Java compiler will check for type safety on everything.

Your templates need to extend your application-specific template

There are two ways you can instruct a template to extend a specific superclass. First, you can do it in the maven plugin:

<build>
    <plugins>
        <plugin>
            <groupId>com.fizzed</groupId>
            <artifactId>rocker-maven-plugin</artifactId>
            <version><!-- version here --></version>
            <executions>
                <execution>
                    <id>generate-rocker-templates</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <extendsClass>utils.ApplicationRockerTemplate</extendsClass>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Alternatively, your template can set an option for itself

@option extendsClass=utils.ApplicationRockerTemplate

@args (String title)

<h1>@title</h1>

Common issues

If your Ninja project compiles and runs, but you get a runtime error like this:

ERROR c.f.n.rocker.TemplateEngineRocker - Unable to handle renderable not of type: class views.ApplicationController.helloWorld

You likely forgot to configure your rocker maven plugin to "extendsClass" from code>com.fizzed.ninja.rocker.NinjaRockerTemplate. See below for more info.

If your project won't compile and you see compiler warnings like:

[ERROR] /fizzed/java-ninja-rocker/demo/target/generated-sources/rocker/views/ninja.java:[162,65] cannot find symbol
[ERROR] symbol:   variable N

You most likely did not configure your rocker maven plugin to extend templates from com.fizzed.ninja.rocker.NinjaRockerTemplate rather than the default of com.fizzed.rocker.runtime.DefaultRockerTemplate. The "N" variable is defined in com.fizzed.ninja.rocker.NinjaRockerTemplate.

The configuration section for your rocker plugin for maven should look like this:

License

Copyright (C) 2016 Fizzed, Inc.

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

ninja-rocker's People

Contributors

jjlauer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

ninja-rocker's Issues

ninja context availability in subclasses of NinjaRockerTemplate

I've use own subclass of NinjaRockerTemplate with a helper for views
and this helper need access to ninja context
Like this:
public abstract class LavinaRockerTemplate extends NinjaRockerTemplate {
...
public LavinaRocker L;
@OverRide
public void injectContext(NinjaProperties ninjaProperties, Router router, Messages messages, Lang lang, Context context, Result result) {
super.injectContext(ninjaProperties, router, messages, lang, context, result);
L = new LavinaRocker(ninjaProperties, router, messages, lang, result, context);
}
...
}

NullPointerException caused by @N.reverseRoute

I've got Ninja and Rocker running and they have already been producing results. I wanted to include reverseRoutes in my page and used <div>@N.reverseRoute(PerformanceController.class,"work","asdasd")</div> to generate them. This always triggers NullPointerExceptions with the given the following stacktrace

Evaluating line 10 of work.rocker.html alone gives me "there", additionally the stacktrace says the NPE is somewhere else.

Routes is also setup to work I think.

I have all files I think are relevant In this gist: https://gist.github.com/awildturtok/812602892d8a58779d8e

I'm running on Windows 8 with Java 1.8 properly configured in Maven.

Cannot find symbol N

For some reason i am getting compilation issues when trying to compile my file with Ninja rocker.

it gives me the following error where ever i try use the N veriable.

[ERROR] /C:/work/personal/ninja-cdms/target/generated-sources/rocker/views/ApplicationController/index.java:[78,32] cannot find symbol
[ERROR] symbol: variable N

Do i need to pass this n variable through some how?

Call out need for additional build config

Similar to #1 (which I did not see until I had fixed the issue below)

I was trying to set up a "hello world" type app using a simple Ninja app I had created following Ninja's framework tutorials. I was able to get rocker templates to generate without too much of an issue but spent many hours with errors such as

[qtp1018937824-17] ERROR c.f.n.rocker.TemplateEngineRocker - Unable to handle renderable not of type: class views.ApplicationController.index

The fix was easy enough - adding the following to the build plugin

 <configuration>
    <extendsClass>com.fizzed.ninja.rocker.NinjaRockerTemplate</extendsClass>
 </configuration>

With final result looking like

<plugin>
<groupId>com.fizzed</groupId>
<artifactId>rocker-maven-plugin</artifactId>
<version>0.9.0</version>
<executions>
    <execution>
        <id>generate-rocker-templates</id>
        <phase>generate-sources</phase>
        <goals>
            <goal>generate</goal>
        </goals>
        <configuration>
            <extendsClass>com.fizzed.ninja.rocker.NinjaRockerTemplate</extendsClass>
        </configuration>
    </execution>
  </executions>
 </plugin>

A few things I would suggest

  1. Update ninja-rocker READMe with explicit call out to this. The instructions say to use Rockers build plug-in XML, but that is not sufficient
  2. Improve error message if possible. Unable to handle renderer did not make me think this was the fix.
  3. A simpler hello world app outside of the demo.
    1. The simplest demo page still uses templates that call templates
    2. Demo's POM having a parent and project being nested a bit confusing

I had spent a lot of my time thinking I had template specific issues. Such as the case in #1 thinking N needed to be passed through. I will take a shot at the third item - creating a demo app. I like the existing demo app and don't think it needs to change. Just a simpler app if people are having even the most basic of basic issues, such as getting 'Hello World' to display.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.