Closure Tools

Hello World Using Java

  1. Hello World
  2. Hello Name and Hello Names
  3. Using Guice
  4. Using SoyParseInfoGenerator

Hello World

Follow these steps to create a simple Hello World template and use it in Java:

  1. Download closure-templates-for-java-latest.zip from the Closure Templates project hosting site.

    This archive contains the following files:

    • soy-latest.jar — A standalone jar file that contains all the Closure Templates classes and their dependencies.
    • SoyParseInfoGenerator.jar — A standalone executable jar that parses Soy files and generates Java classes that contain information such as template and parameter names. You will use this file later in the Using SoyParseInfoGenerator section.

  2. Put these files in your working directory, for example in:

    ~/helloworld_java/
    
  3. All files that contain Closure Templates end with the .soy file extension and are called Soy files. Create a file in this directory called simple.soy and copy this line to the file:

    {namespace examples.simple}
    

    This line declares a namespace for all the templates that you define in this file.

  4. Copy the following basic template to the file, making sure that it appears after the namespace declaration:

    /**
     * Says hello to the world.
     */
    {template .helloWorld}
      Hello world!
    {/template}
    
    

    This template simply outputs the text "Hello world!". It has the partial name .helloWorld, which, when combined with the namespace, forms the fully qualified template name examples.simple.helloWorld.

  5. In the same directory as simple.soy, create a file called HelloWorld.java and copy the following contents into the file:

    import com.google.template.soy.SoyFileSet;
    import com.google.template.soy.data.SoyMapData;
    import com.google.template.soy.tofu.SoyTofu;
    
    import java.io.File;
    
    public class HelloWorld {
    
      public static void main (String[] args) {
    
        // Bundle the Soy files for your project into a SoyFileSet.
        SoyFileSet sfs = new SoyFileSet.Builder().add(new File("simple.soy")).build();
    
        // Compile the template into a SoyTofu object.
        // SoyTofu's newRenderer method returns an object that can render any template in the file set.
        SoyTofu tofu = sfs.compileToTofu();
    
        // Render the template with no data.
        System.out.println(tofu.newRenderer("examples.simple.helloWorld").render());
      }
    
    }
    

    This example bundles the template files that you specify (in this case, just simple.soy) into a SoyFileSet object, then compiles the bundle into a SoyTofu object form with a call to compileToTofu(). The final line of code calls the template, using the template's fully qualified name examples.simple.helloWorld, and renders its output to standard out.

  6. To try out this example, you'll need to have Java Development Kit (JDK) version 6 installed, with the executables java and javac on your path. Compile the HelloWorld class:

    ~/helloworld_java$ javac -classpath soy-latest.jar HelloWorld.java
    
  7. Run this command to see the rendered template:

    ~/helloworld_java$ java -classpath .:soy-latest.jar HelloWorld
    

    In this example, classpath contains the current directory (for HelloWorld.class) as well as soy-latest.jar for the HelloWorld class's dependencies.

    Note: On Windows, use a semicolon instead of a colon as the path separator.

    Note: On some systems, you might need to use single quotes to delimit your classpath string.

    You should see this message at standard out:

    Hello world!
    
  8. That's it! Now that you've created a simple Hello World template and used it in Java, you can try more exercises in the next section.

    Hello Name and Hello Names

  9. Add the following second template, called .helloName, to simple.soy. Note that .helloName takes a required parameter called name, which is declared by @param. It also takes an optional parameter greetingWord, which is declared by @param?. These parameters are referenced in the template body using the expressions $name and $greetingWord, respectively. This template also demonstrates that you can conditionally include content in templates via the if-else commands. You can put this template before or after the .helloWorld template, just as long as it's after the namespace declaration.

    /**
     * Greets a person using "Hello" by default.
     * @param name The name of the person.
     * @param? greetingWord Optional greeting word to use instead of "Hello".
     */
    {template .helloName}
      {if not $greetingWord}
        Hello {$name}!
      {else}
        {$greetingWord} {$name}!
      {/if}
    {/template}
    
  10. Add a third template to the file. This template, helloNames, demonstrates a foreach loop with an ifempty command. It also shows how to call other templates and insert their output using the call command. Note that the data="all" attribute in the call command passes all of the caller's template data to the callee template.

    /**
     * Greets a person and optionally a list of other people.
     * @param name The name of the person.
     * @param additionalNames The additional names to greet. May be an empty list.
     */
    {template .helloNames}
      // Greet the person.
      {call .helloName data="all" /}<br>
      // Greet the additional people.
      {foreach $additionalName in $additionalNames}
        {call .helloName}
          {param name: $additionalName /}
        {/call}
        {if not isLast($additionalName)}
          <br>  // break after every line except the last
        {/if}
      {ifempty}
        No additional people to greet.
      {/foreach}
    {/template}
    

    Note: Make sure that you've added the new templates after the namespace declaration.

  11. Now edit HelloWorld.java and add the lines of bolded code below (note the new import), which call the new templates and exercise them with data:

    import com.google.template.soy.SoyFileSet;
    import com.google.template.soy.data.SoyListData;
    import com.google.template.soy.data.SoyMapData;
    import com.google.template.soy.tofu.SoyTofu;
    
    import java.io.File;
    
    public class HelloWorld {
    
      public static void main (String[] args) {
    
        // Bundle the Soy files for your project into a SoyFileSet.
        SoyFileSet sfs = (new SoyFileSet.Builder()).add(new File("simple.soy")).build();
    
        // Compile the template into a SoyTofu object.
        // SoyTofu's newRenderer method returns an object that can render any template in file set.
        SoyTofu tofu = sfs.compileToTofu();
    
        // Render the template with no data.
        System.out.println(tofu.newRenderer("examples.simple.helloWorld").render());
    
        // For convenience, create another SoyTofu object that has a namespace specified,
        // so you can pass partial template names to the newRenderer() method.
        SoyTofu simpleTofu = tofu.forNamespace("examples.simple");
    
        // Hello Name example
        System.out.println("-----------------");
        // Map the parameter "name" to the string "Ana"
        System.out.println(simpleTofu.newRenderer(".helloName")
                           .setData(new SoyMapData("name", "Ana")).render());
    
        // Hello Names example
        System.out.println("-----------------");
        System.out.println(simpleTofu.newRenderer(".helloNames")
            .setData(new SoyMapData(
                "name", "Ana",
                "additionalNames", new SoyListData("Bob", "Cid", "Dee")))
            .render());
      }
    
    }
    

    This example exercises the .helloName template with a SoyMapData object in which the parameter "name" is mapped to the string "Ana". For the .helloNames template, the example maps the parameter "additionalNames" to a list of strings "Bob", "Cid", "Dee".

  12. Now that you've added in new templates and updated the example to call them, re-compile and run them. You should see these messages at standard out:

    ~/helloworld_java$ javac -classpath soy-latest.jar HelloWorld.java
    ~/helloworld_java$ java -classpath .:soy-latest.jar HelloWorld
    Hello world!
    -----------------
    Hello Ana!
    -----------------
    Hello Ana!<br>Hello Bob!<br>Hello Cid!<br>Hello Dee!
    

Using Guice

If your application uses Guice, you can inject Soy classes such as SoyFileSet.Builder instead of constructing them yourself. Your Guice injector must contain SoyModule, and if your application needs localization, you should also include the appropriate message plugin module such as XliffMsgPluginModule.

For example, if you used Guice, the Hello World example from the previous section would start like this (with three additional import lines not shown):

    // Create a Guice injector that contains the SoyModule and use it get a SoyFileSet.Builder.
    Injector injector = Guice.createInjector(new SoyModule());
    SoyFileSet.Builder sfsBuilder = injector.getInstance(SoyFileSet.Builder.class);

    // Bundle the Soy files for your project into a SoyFileSet.
    SoyFileSet sfs = sfsBuilder.add(new File("simple.soy")).build();

Using SoyParseInfoGenerator

You might find it error-prone to type hard-coded strings for template names and template parameters. If so, you can use SoyParseInfoGenerator to generate Java constants for the template and parameter names in your templates. Follow the steps below to use SoyParseInfoGenerator with the Hello World example:

  1. Recall that you downloaded SoyParseInfoGenerator.jar in an earlier step and placed the file in ~/helloworld_java/. This file is a standalone executable jar that parses Soy files and generates Java classes that contain information such as template and parameter names.

    Run SoyParseInfoGenerator with the following command-line flags:

    ~/helloworld_java$ java -jar SoyParseInfoGenerator.jar --outputDirectory generated --javaPackage generated --javaClassNameSource filename --srcs simple.soy
    

    This step creates the directory ~/helloworld/generated and generates a file in it called SimpleSoyInfo.java. This file contains mappings between the generated constants and their corresponding strings.

    Open SimpleSoyInfo.java and take a look at the constants that SoyParseInfoGenerator generated for each of the templates and their parameters. For example, the Java constant HELLO_NAME maps to a SoyTemplateInfo object that represents the .helloName template, and the constant HELLO_NAME.NAME maps to the .helloName template's parameter "name".

  2. Edit HelloWorld.java and replace the contents of the file with the code below. Note that the differences between this file and the original are bolded.

    import static generated.SimpleSoyInfo.HELLO_NAME;
    import static generated.SimpleSoyInfo.HELLO_NAMES;
    import static generated.SimpleSoyInfo.HELLO_WORLD;
    
    import com.google.template.soy.SoyFileSet;
    import com.google.template.soy.data.SoyMapData;
    import com.google.template.soy.tofu.SoyTofu;
    import com.google.template.soy.data.SoyListData;
    
    import java.io.File;
    
    public class HelloWorld {
    
      public static void main (String[] args) {
    
        SoyFileSet sfs = (new SoyFileSet.Builder()).add(new File("simple.soy")).build();
    
        SoyTofu tofu = sfs.compileToTofu();
        System.out.println(tofu.newRenderer(HELLO_WORLD).render());
    
        System.out.println("-----------------");
        System.out.println(tofu.newRenderer(HELLO_NAME)
                           .setData(new SoyMapData(HELLO_NAME.NAME, "Ana")).render());
    
        System.out.println("-----------------");
        System.out.println(tofu.newRenderer(HELLO_NAMES)
            .setData(new SoyMapData(
                HELLO_NAMES.NAME, "Ana",
                HELLO_NAMES.ADDITIONAL_NAMES, new SoyListData("Bob", "Cid", "Dee")))
            .render());
      }
    
    }
    
  3. Compile the HelloWorld and SimpleSoyInfo classes:

    ~/helloworld_java$ javac -classpath soy-latest.jar HelloWorld.java generated/SimpleSoyInfo.java
    
  4. Finally, re-run the example and you should see the same output as before:

    ~/helloworld_java$ java -classpath .:soy-latest.jar HelloWorld
    Hello world!
    -----------------
    Hello Ana!
    -----------------
    Hello Ana!<br>Hello Bob!<br>Hello Cid!<br>Hello Dee!
    
  5. You've just completed the Hello World of Closure Templates using Java. Where should you go next?

    • To use the same templates from this chapter in JavaScript, try the Hello World Using JavaScript examples.
    • To read more about Closure Templates concepts, take a look at the Concepts chapter.

Authentication required

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

Signing you in...

Google Developers needs your permission to do that.