Community contributed extensions

Integration Guide

This section is PlayRythm specific content, pure Rythm user should skip this section

Migrate your current project from Groovy template engine to Rythm

PlayRythm is designed to support smooth migrating from Groovy template engine.

PlayRythm hijack the template rendering process if it found the corresponding template exists in the app/rythm folder. Otherwise it quit silently and leave groovy engine to handle it. So what you need to do is just create an new template file using Rythm syntax and put it into the app/rythm folder. Before your new rythm template available your existing groovy template works like a charm, and after the rythm template created, Rythm will take over

See Step by step migrate groovy template to rythm.

Configuration

PlayMorphia provides default value for all configuration items, thus enable it to be used with zero configuration.

namedescriptiondefault value
rythm.cache.prodOnlySet if cache service enabled only on prod mode. If true then cache service is disabled on dev modetrue
rythm.cache.defaultTTLSet default timeout duration in seconds3600 seconds
rythm.gaeSet this to true if running in GAE. This will disable bytecode cache in Rythmfalse
rythm.noFileWriteSame effect as rythm.gaefalse
rythm.compactOutputIf true then output content in compact mode, i.e. additonal white space and line breaks will be removedtrue in prod mode

Resolve groovy compilation error

Because groovy template engine does not provide a way to skip parsing any part of the template file, the rythm template file might cause compilation error during precompile process, where rythm has no way to identify some files been a rythm template or groovy template, e.g. some json generation template.

Start from version 0.9.5 it’s suggest to move all rythm templates or at least those compilation error causing templates to app/rythm folder from app/views folder.

Start from version 1.0.0 app/views folder as template root as no longer supported, please move all rythm view files into app/rythm folder. And there will be no groovy compilation error any more caused by rythm template

Customize Template Class

Start from v1.0.0-20121103, it allowed developer to customize template class by adding methods and imports to each template class generated by PlayRythm.

Add common imports to all template class

In order to add any arbitrary imports to all templates you can create a file named __add_on.import to app/rythm directory. Inside the file you add the staff needs to be imported one item at a line. For example:

play.modules.aaa.utils.AAA
play.modules.aaa.IAccount
play.modules.aaa.IRole
play.modules.aaa.IRight

After you added the imports, you can use those imported items in any one of your templates:

@extends(main)
<div id="top-bar">
...
<span class="welcome">
Welcome @AAA.me().getName()!
</span>
</div>
@if (AAA.isSuperUser()){
    ...
} else {
    ...
}

Add common methods to all template class

You can add any arbitrary method to all template class by put in them into a file named __add_on.src under app/rythm folder. For example:

// determine if current user has a certain role
protected boolean hasRole(String... roles) {
    return AAA.hasRole(roles);
}
// check if current user is an admin
protected boolean isAdmin() {
    return hasRole("admin");
}
// check if current user is a manager
protected boolean isManager() {
    return hasRole("manager");
}

After you’ve added the customized methods, you can use them in any template:

@if (isAdmin()) {
    <div class="admin-panel">
    ...
    <div>
} else if (isManager()) {
    <div class="manager-panel">
    ...
    </div>
} else {
    ...
}

_url methods in template class

Specifically, PlayRythm (start from v1.0.0-20121103) add an new method named _url() to all template class so that you can use reverse url lookup easily in function call:

Example 1: use @url() tag:

$.post([email protected](MyController.myAction)', {id: ...}, function(resp){...})

Example 2: use _url() method in script block:

@{String link = _url(true, "Clients.resetPasswordForm") + "?token=" + token;}

Example 3: use _url() method in tag call:

@def link(String label, String link, boolean showLink) {
    @if(showLink) {<a href="@link">@label</a>}
    else {<span>@label</span>}
}
@section("topactions") {
    @link("Profile", _url("client", client.getId()), !_profile)
    @link("Users", _url("clientUser", client.getId()), !_user)
    @link("Subscription", _url("clientSubscription", client.getId()), !_sub)
}

There is one difference between passing parameters to @url() tag and _url() method:

Passing parameter to @url() tag:

$.get([email protected](Application.myProfile(user.getId()))', function(resp){})

Passing parameter to @_url() method call:

@{String link = _url("Application.myProfile", user.getId())}

_msg methods in template class

Specifically, PlayRythm (start from v1.0.0-20121106) add an new method named _msg() to all template class so that you can lookup message files easily in function call:

Example 1: use @msg() tag:

<h1>@msg("application.title")</h1>

Example 2: use _msg() method in script block:

@{String title = _msg("application.title");}

Example 3: use _msg() method in tag call:

@def link(String label, String link, boolean showLink) {
    @if(showLink) {<a href="@link">@label</a>}
    else {<span>@label</span>}
}
@section("topactions") {
    @link(_msg("client.profile"), _url("client", client.getId()), !_profile)
    @link(_msg("client.user"), _url("clientUser", client.getId()), !_user)
    @link(_msg("client.subscription"), _url("clientSubscription", client.getId()), !_sub)
}

More about tags

So far you can keep rythm tags file under app/views/tags/rythm folder. However it is recommened not to use tags folder at all since every rythm template is a tag and can be called from any other rythm templates.

Start from v1.0.0, app/views/tags/rythm folder as tag root are no longer supported. Please just use app/rythm folder as template root and also the tag root.

E.g. suppose you have a template file app/views/Order/list.html, while you can use it as an ordinary template file, you also free to call it as a tag from other rythm template like: @Order.list(myOrders)

Invoking controller actions

PlayRythm 0.9.7 version released with this new feature which is first introduced in Japid template engine and people seems like it a lot. Basically you can invoke a controller action method directly from within the template and fill the place with the render result content. As with any function/tag/template invocation, action method invoke is very straghtforward. Excamples:

@controllers.Applicaiton.index().cache("1h");
@controllers.MyPortal.newsPanel(user);

Things you need to take care of:

  1. You must use full qualified method name (including package name, class name) when you invoke controller action method No longer required since v1.0.0
  2. You must pass exactly the parameters that matches what is defined in the controller action method signature. The parameter must be passed in by position
  3. The invocation is directly and will not go through the whole stack of Play’s action invocation process. Meaning the @Before, @After and @Final logic will NOT be executed, the same thing happens to all plugin’s beforeActionInvocation(), onActionInvocationResult() and afterActionInvocation() hooks.
  4. Start form v1.0 controller invocation is eligible to the following tag invocation extensions:
    1. Cache: @controllers.Application.index().cache(“1h”)
    2. Invoke with relative path/import path: @import controllers.*; @Application.index()
    3. Assign action result to a variable: @controllers.Application.index().cache(“1h”).assign(“indexPage”). And you can use it as a normal template variable later on: @indexPage.raw()
    4. Escape/un-escape render result: @controllers.Application.index().raw()

New Cache4 annotation for caching action invocation

Though not so relevant to a template engine, Rythm still provides an new annotation com.greenlaw110.rythm.play.Cache4 for controller action (GET and HEAD) result caching. It improves the Play’s built-in play.cache.CacheFor in the following way:

Sample:

@Cache4("cron.top10.cache")
public static void displayTop10() {
...
}

In your conf/application.conf:

cron.top10.cache=5mn

You can set useSessionData attribute to true to create a per-user-cache mechanism:

@Cache4(useSessionData = true, value="1h")
public static void showMyInterests() {
...
}

Use key parameter if you want to define a customized key provider class:

@Cache4(key = MyCacheKeyProvider.class)
public static void load(String pageId) {
...
}

Where MyCacheKeyProvider could be:

public class MyCacheKeyProvider extends extends ICacheKeyProvider.Default {
    @Override
    public String getKey() {
        return params().get("pageId");
    }
}

The default key provider returns "rythm-urlcache:" + request.url + request.querystring as the cache key.

In certain cases you probably want to cache post requests. For example, facebook always use POST requests when needs to load the tab page inside it’s iframe. In this case you can set cachePost to true:

@Cache4(cachePost = true)
public static void loadLandingPage() {
...
}

Cache4 side effects

Cache4 logic is implemented in RythmPlugin.beforeActionInvocation() and RythmPlugin.onActionInvocationResult() hooks. This indicates the following side effects of Cache4:

So you should NOT use Cache4 annotation in the following cases:

For module or application defined filters that will throw out non-permanent Redirect result, for example, secure module will cause redirect if user has not logged in, in which case you are still safe to use Cache4 with useSessionData enabled. See above example.

@Cache4 does not require you to use Rythm template, it works with any controller action methods

See Also

  1. Rythm Template User guide
  2. Reference manual