8

Yes, I know that this has been asked before. But most of the questions were two years ago, and there's got to be a better answer today.

I need a template language for rendering HTML. Requirements:

  1. Must be callable from Java.

  2. Must not be Freemarker, Velocity, or StringTemplate. We've been using Freemarker for a year, and it's too slow. It consumes 50% of our CPU cycles under load. Velocity is worse than Freemarker, and StringTemplate has got its own issues.

  3. It must consume JSON, or its Java equivalent, i.e. Maps, Lists, and primitives.

I'm starting to get Node.js envy. There has been a ton of template activity for Javascript in the last year, but little for Java (that I know of).

The ideal language would look like Liquid, which exists only for Rails.

Jade exists for Java, but I don't want all the HTML reformatting that comes with it.

Update

I eventually settled on Handlebars, which is also available for Java. Both work great.

Community
  • 1
  • 1
ccleve
  • 15,239
  • 27
  • 91
  • 157
  • Already argumentative in statement of question. How can this be constructive? – Don Roby May 09 '12 at 22:00
  • Fixed. Didn't intend to be argumentative. – ccleve May 09 '12 at 22:12
  • Could you elaborate a bit on why you consider Velocity as worse than Freemarker? I've never encountered such system consumptions with it. – Claude Brisson May 10 '12 at 09:36
  • You can use SpEL (Spring Expression Language). It's fast, stable, and has more modern operators than Velocity or Freemarker. – Mohsen May 10 '12 at 18:52
  • Are you guys using caching at all? We're caching the generated HTML for content that doesn't change all that often and leaving the very dynamic (ie. user session) content as non-cached. That might help you with your CPU issues. – geekonablog May 10 '12 at 20:55
  • Out of curiosity, what part of FreeMarker was responsible for eating up that much CPU and in what kind of application? – ddekany May 11 '12 at 00:09
  • On caching: we cache the parsed freemarker template, but not the HTML, because it has dynamic content on every page fetch. – ccleve May 11 '12 at 16:51
  • 2
    I've got to agree with ddekany (and Claude). I've been around Freemarker and Velocity for years and never heard of 50% CPU. Odds are very high that you are doing something wrong. Check your loops, maybe. – Nathan Bubna May 14 '12 at 15:21

2 Answers2

4

Chunk is json-friendly. JSON can be used as a tag value in your controller code or in the templates themselves for exec/macro calls.

{% exec %}
  {% data @json %}
    { name: "whatever",
      vitals: ["an","array","of","data"],
      friends: [{name: "bob"},{name: "crystal"}]
    }
  {% enddata %}

  <div>Name: {$name}</div>

  {% if ($friends) %}
    <div>Friends:

      <ul>
      {% loop in $friends as $friend %}
        <li>{$friend.name}</li>
      {% endloop %}
      </ul>

    </div>
  {% endif %}

{% endexec %}

Or, just use the inner template and inject the json from the java side.

src/themes/example.chtml

  <div>Name: {$name}</div>

  {% if ($friends) %}
  <div>Friends:

    <ul>
    {% loop in $friends as $friend %}
     <li>{$friend.name}</li>
    {% endloop %}
    </ul>

  </div>
  {% endif %}

MyController.java

Theme theme = new Theme();
Chunk html = theme.makeChunk("example");

html.set("name", "whatever");
html.set("vitals", getJsonArray() );
html.set("friends", getJsonFriendObjects() );

html.render( out );

As long as the getJsonXXX() methods return something that implements List and Map, Chunk will glue it into the template correctly (even if those Lists and Maps nest more Lists and Maps).

Output:

<div>Name: whatever</div>

<div>Friends:

  <ul>
   <li>bob</li>
   <li>crystal</li>
  </ul>

</div>
Tom McClure
  • 6,699
  • 1
  • 21
  • 21
0

Java+ is a simple preprocessor solution. It just stringifies markup:

System.out.println({{
 <html>
  <body>
   ...
  </body>
</html>}})

It has configurable delimiters and passes through Java code rather than consuming it:

System.out.println({{
<xmlExample>
  <name>{{fpp}}</name>
  <number>{{bar}}</number>
</xmlExample>
}});

References

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265