Closure Tools

Using Closure Templates in Java

  1. Compilation
  2. Rendering
  3. Constructing Template Data
  4. Creating Message Bundles
  5. Globals
  6. Using SoyParseInfoGenerator
  7. API Javadoc
  8. Code Examples

Compilation

The Closure Templates' Tofu backend compiles a set of template files into a Java object representation (called SoyTofu), which has a method to render any of the templates in the file set. To compile a set of template files for use in Java, first construct a SoyFileSet (package com.google.template.soy) with the complete set of input files. You can provide each input as a File, resource URL, CharSequence, or InputSupplier<? extends Reader>. Then use SoyFileSet.compileToTofu() to compile to a Java object representation of your templates. The result will be in the form of a SoyTofu instance (package com.google.template.soy.tofu).

Example code if your application does not use Guice:

SoyFileSet sfs = (new SoyFileSet.Builder()).add(...).add(...).build();
SoyTofu tofu = sfs.compileToTofu();

Example code using Guice:

Injector injector = Guice.createInjector(..., new SoyModule(), new XliffMsgPluginModule());
SoyFileSet.Builder sfsBuilder = injector.getInstance(SoyFileSet.Builder.class);
SoyFileSet sfs = sfsBuilder.add(...).add(...).build();
SoyTofu tofu = sfs.compileToTofu();

Rendering

To render a template in Java, you can directly use the SoyTofu object that you obtained from compilation, or you can create a new SoyTofu object that is bound to a particular namespace.

Call SoyTofu.newRenderer() with the name of the template to render or a SoyTemplateInfo object that represents the template (the latter is defined by code generated by SoyParseInfoGenerator, which is explained in the Using SoyParseInfoGenerator section below). If you're using a namespaced SoyTofu object, then supply a partial template name starting with a dot. If you're using a non-namespaced SoyTofu object, then supply a full template name.

The Renderer has setter methods to let you further configure your render:
  • setData(): You can use either a SoyMapData object or a Map<String, ?> (for details, see the subsection on constructing template data). The template data can also be null if the template has no required parameters.
  • setIjData(): Same as setData(), but for setting injected data (if applicable).
  • setMsgBundle(): Specifies which SoyMsgBundle contains translated messages to use instead of the originals in the template (for details, please see the subsection on creating message bundles).

Note: you need to call render() after configuring your Renderer.

Here is an example template (assume the file's namespace is soy.examples.simple):
/**
 * Says hello to a person.
 * @param name The name of the person to say hello to.
 */
{template .helloName}
  Hello {$name}!
{/template}
Here is the corresponding example usage:
String output1 = tofu.newRenderer("soy.examples.simple.helloName")
    .setData(new SoyMapData("name", "Jen"))
    .setMsgBundle(msgBundle)
    .render();
String output2 = tofu.newRenderer("soy.examples.simple.helloName")
    .setData(ImmutableMap.<String, String>of("name", "Jen"))
    .setMsgBundle(msgBundle)
    .render();
SoyTofu simpleTofu = tofu.forNamespace("soy.examples.simple");
String output3 = simpleTofu.newRenderer(".helloName")
    .setData(new SoyMapData("name", "Jen"))
    .setMsgBundle(msgBundle)
    .render();
String output4 = simpleTofu.newRenderer(".helloName")
    .setData(ImmutableMap.<String, String>of("name", "Jen"))
    .setMsgBundle(msgBundle)
    .render();

In the output, you would see that output1, output2, output3, and output4 would all be rendered "Hello Jen!" (but possibly translated depending on the msgBundle).

Constructing Template Data

A data object is either a SoyMapData instance or a Map<String, ?>, for example:

SoyMapData data = new SoyMapData(
    "name", "Melissa",
    "destinations", new SoyListData("Singapore", "London", "New York"));
Map<String, Object> data = ImmutableMap.<String, Object>of(
    "name", "Melissa",
    "destinations", ImmutableList.of("Singapore", "London", "New York"));

Constructing a SoyMapData

Closure Templates have a hierarchy of mostly internal Java classes that implement all the template data types. You can find the public classes in package com.google.template.soy.data:

  • SoyData – The base class for all data tree nodes.
  • SoyMapData – Data node representing a map.
  • SoyListData – Data node representing a list.

The root of a data tree must be a SoyMapData. Other internal nodes in the tree (if any) can either be SoyMapData or SoyListData.

The classes SoyMapData and SoyListData support multiple forms of put(), remove(), and get(), and SoyListData also supports length() and multiple forms of add() and set(). Check the Javadoc for full details.

The table below lists the template data types and their corresponding Java types:

Template Type Java Type
Null (SoyData) null
Boolean boolean
Integer int
Float double
String String
List SoyListData
Map SoyMapData

Note that the classes SoyData, SoyMapData, and SoyListData do not allow you to construct an invalid template data tree. In fact, even the convenient constructors and methods that let you put or add many mappings and elements at once (and take Object... as the type of all the varargs parameters) check every value and convert it to an internal SoyData value (if valid) or throw an exception (if invalid).

Note: You can use the static function SoyData.createFromExistingData() to convert an arbitrary value of unknown type to a SoyData object. The function throws an exception if the value is not a valid data value.

Using a Java Map

You can also pass a Map<String, ?> directly as the data for a template, although this is purely for convenience. Internally, the first thing the template compiler does is convert this Map<String, ?> into a new SoyMapData and then proceeds to do the rendering. The conversion is performed simply using the SoyMapData constructor that takes in a Map<String, ?> as its initial data (note the conversion is deep, not shallow). Thus, the following are equivalent:

simpleTofu.newRenderer(".myTemplate").setData(myMap).render();
simpleTofu.newRenderer(".myTemplate").setData(new SoyMapData(myMap)).render();

For efficiency, it doesn't really matter what you do if you only need to make one call to render() using a particular template data object. However, if you need to reuse the same template data object for multiple calls to render(), you should create a SoyMapData and reuse it. Otherwise, if you use the same Map<String, ?> to render multiple templates, the templates compiler converts it each time to a new SoyMapData. Whether your SoyMapData is built from scratch or initially created via the constructor new SoyMapData(Map<String, ?>) should not make a big difference.

Creating Message Bundles

The SoyMsgBundle class (package com.google.template.soy.msgs) is the internal representation of a message bundle, and is the object you need to pass to the SoyTofu.Renderer.setMsgBundle() methods to render a template with localized messages. See the Translation chapter for more information.

Globals

A global is data that is not explicitly passed into the template as a parameter, but instead is expected to be provided directly to the compiler during template compilation. In Java usage, all globals must be bound at compile time. To supply a mapping of globals to the template compiler, use one of the three SoyFileSet.Builder.setCompileTimeGlobals() methods. (Note: these three methods have the same name but different argument types.) You can supply either a Map<String, ?>, where each value must be of a primitive type, or a File or resource URL (in the file format described in the bulleted item below).

Each line of the file should follow this format:

<global_name> = <primitive_data>

where <primitive_data> is a valid template expression literal for a primitive type (null, boolean, integer, float, or string). For example:

GLOBAL_INT = 26
myapp.GLOBAL_BOOL = true
myapp.silly.GLOBAL_STR = 'I\'m a string.'

Follow these guidelines when creating your globals file:

  • The template compiler ignores empty lines and lines that begin with //.
  • Encode the file in UTF-8.
  • If you need to generate a file in this format from Java, consider using the utility SoyUtils.generateCompileTimeGlobalsFile() (package com.google.template.soy).

Using SoyParseInfoGenerator

As a convenience, you can use SoyParseInfoGenerator to generate Java files containing info parsed from your template files, including templates and parameter names, so that you can avoid the error-prone process of manually typing template and parameter names as strings.

Follow this command syntax to run SoyParseInfoGenerator:

java -jar SoyParseInfoGenerator.jar [<flag1> <flag2> ...] --outputDirectory <path>  \
          --javaPackage <package> --javaClassNameSource <source>  \
          --srcs <soyFile1>,<soyFile2>,...

These are the command line flags that you can use with SoyParseInfoGenerator:

Flag Usage
--srcs [Required] The list of source Soy files.
--outputDirectory [Required] Set this to the path of the output directory that you want the generated Java classes to be written to. If files with the same names already exist at this location, the template compiler overwrites them.
--javaPackage [Required] Set this to the Java package name to use for the generated classes.
--javaClassNameSource

[Required] Use this flag to set the name of the generated Java class names. Valid values are:

  • filename: Generates the class AaaBbbSoyInfo for a Soy file named AaaBbb.soy or aaa_bbb.soy.
  • namespace: Appends SoyInfo to the last part of a namespace. For example, generates a class called CccDddSoyInfo for the namespace aaa.bbb.cccDdd.
  • generic: Generates generic class names such as File1SoyInfo, File2SoyInfo, etc, enumerating these names in the same order as you passed them in.
--inputPrefix Set this to the path prefix that should be prepended to each input file path that is listed on the command line. This is a literal string prefix, so be sure to include a trailing slash if necessary.

API Javadoc

For a full API reference, take a look at one of two versions of the Javadoc:

Code Examples

You can check out simple and complex code examples of Java usage from the Subversion repository. These code examples have corresponding Ant build targets. To try these out, check out the project from Subversion:

http://code.google.com/p/closure-templates/source/checkout

The files for Java examples are in:

  • examples — shared examples files
  • java/src/com/google/template/soy/examples — Java-specific examples files

These directories each have a file called README_FOR_EXAMPLES that explains their contents.

To try these examples, build and then run the corresponding Ant target (java-simple-example or java-features-example). Each target builds an executable jar that renders the examples.

The features examples depend on generated Java files that are supplied in the directories listed above. Refer to the README_FOR_EXAMPLES files in each directory to see the names of the Ant targets that correspond to these generated Java files. Then look for the definitions of these Ant targets in build.xml, which is at the top-level.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.