-
-
Save vybs/1624130 to your computer and use it in GitHub Desktop.
package com.linkedin.dust.renderer; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.Reader; | |
import java.io.Writer; | |
import org.mozilla.javascript.Context; | |
import org.mozilla.javascript.JavaScriptException; | |
import org.mozilla.javascript.Scriptable; | |
public class DustEngine | |
{ | |
public static final String MODULE = DustEngine.class.getName(); | |
private static Scriptable globalScope; | |
public DustEngine(InputStream dustStream) | |
{ | |
try | |
{ | |
Reader dustReader = new InputStreamReader(dustStream, "UTF-8"); | |
Context dustEngineContext = Context.enter(); | |
dustEngineContext.setOptimizationLevel(9); | |
try | |
{ | |
globalScope = dustEngineContext.initStandardObjects(); | |
dustEngineContext.evaluateReader(globalScope, | |
dustReader, | |
"dust-compile.js", | |
0, | |
null); | |
} | |
finally | |
{ | |
Context.exit(); | |
} | |
} | |
catch (IOException ex) | |
{ | |
throw new RuntimeException(" ERROR : Unable to load dust engine resource: ", ex); | |
} | |
} | |
public static String compileTemplate(String name, String rawSource) | |
{ | |
Context dustContext = Context.enter(); | |
try | |
{ | |
Scriptable compileScope = dustContext.newObject(globalScope); | |
compileScope.setParentScope(globalScope); | |
compileScope.put("rawSource", compileScope, rawSource); | |
compileScope.put("name", compileScope, name); | |
try | |
{ | |
return (String) dustContext.evaluateString(compileScope, | |
"(dust.compile(rawSource, name))", | |
"JDustCompiler", | |
0, | |
null); | |
} | |
catch (JavaScriptException e) | |
{ | |
// Fail hard on any compile time error for dust templates | |
throw new RuntimeException(e); | |
} | |
} | |
finally | |
{ | |
Context.exit(); | |
} | |
} | |
public static void loadTemplate(String name, String rawSource) | |
{ | |
Context dustContext = Context.enter(); | |
try | |
{ | |
Scriptable compileScope = dustContext.newObject(globalScope); | |
compileScope.setParentScope(globalScope); | |
compileScope.put("rawSource", compileScope, rawSource); | |
compileScope.put("name", compileScope, name); | |
try | |
{ | |
dustContext.evaluateString(compileScope, | |
"(dust.loadSource(dust.compile(rawSource, name)))", | |
"JDustCompiler", | |
0, | |
null); | |
} | |
catch (JavaScriptException e) | |
{ | |
// Fail hard on any compile time error for dust templates | |
throw new RuntimeException(e); | |
} | |
} | |
finally | |
{ | |
Context.exit(); | |
} | |
} | |
public static void render(String name, String json, Writer writer) | |
{ | |
Context dustContext = Context.enter(); | |
Scriptable renderScope = dustContext.newObject(globalScope); | |
renderScope.setParentScope(globalScope); | |
String renderScript = | |
("{ dust.render( name, JSON.parse(json) , function( err, data) { if(err) { writer.write(err);} else { writer.write( data );} } ); }"); | |
try | |
{ | |
renderScope.put("writer", renderScope, writer); | |
renderScope.put("json", renderScope, json); | |
renderScope.put("name", renderScope, name); | |
dustContext.evaluateString(renderScope, | |
renderScript, | |
"JDustCompiler", | |
0, | |
null); | |
} | |
catch (JavaScriptException e) | |
{ | |
// Fail hard on any render time error for dust templates | |
throw new RuntimeException(e); | |
} | |
finally | |
{ | |
Context.exit(); | |
} | |
} | |
} |
Does this actually work with Rhino? I'm getting org.mozilla.javascript.EcmaError: ReferenceError: "window" is not defined. (dust-compile.js#21) errors once the dust-full-0.3.0.min.js file is read into the context object.
you will need the version of dust in
http://linkedin.github.com/dustjs/
We made it Rhino compatible.
I really appreciate the quick response. I have one more question though. I'm new to Java and I don't quite understand what type of writer I would use. I'm just trying to compile the template and return a string of html data. What is the writer used for?
Any form of print writer should be fine.
Since we have the tomcat stack, we directly use the http response writer.
Here is how the render method is invoked
public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception
{
response.setContentType(getContentType());
PrintWriter writer = response.getWriter();
// converts a map to json using jackson json library
DustEngine.render(_name, new ObjectMapper().writeValueAsString(model), writer);
}
Thanks for the helpful code snippet! I got it working.
Some tips for other that may attempt this that are also Java noobs like myself:
- InputStream dustStream can be a URL InputStream which points to the Linkedin dust.js file
- Don't use CompileTemplate and LoadTemplate together. I used LoadTemplate and then RenderTemplate.
- String renderscript looks funky... don't touch it... its right!
ah, some docs in my snippet would have helped ...duh!
So compileTemplate, just compiles and returns the js, calling the render after this, will not work
loadTemplate, compiles and also registers into the dust cache, hence calling the renderTemplate works
A better renderScript!
String renderScript =
("{dust.render(name," +
"JSON.parse(json), " +
"function(err,data) { " +
"if(err) { " +
"writer.write(err);" +
"} " +
"else { " +
"writer.write( data );" +
"} " +
"});}");
Hello, crowd
i really fell in love with dust.js so much, that made a filter, that you can use for web apps. For those interested: http://dust4j.noroutine.me/
It allowed us to write our dust.js templates in JSP, which is much more convenient, compared to manual compilation.
And here it can be seen in action for those interested: http://zion.noroutine.me:8080/tobacco-demo/demo
I'm so new with Java, and do you mind to help me how to use this sample to render dust template on server?
I want to try this your sample with Play framework, and I've created the package and add Rhino jar files to project, what is next stepd i need to do??
thank you........... :) i succesfully executed this code ... Dust is awesome.... :)
@giridharkn glad!. Also checkout the nashorn. It is 10 times faster than rhino
https://blogs.oracle.com/nashorn/
@alohaTu are you still wondering how to? Here is dust plugin you can use with play
https://github.com/typesafehub/play-plugins/tree/master/dust
@vybs : oh, you've came back, long time no see your comments. Thank you very much for your suggestion, but your link , it use for Play 2.x.x and unfortunately my project runs with Play 1.2.5, anyway thank you very much, I will find other solution. :D
@vybs thank you ... sure i try...
Hi All,
Tried to use the specific code and it seems to be throwing me an error . Am trying to invoke a dust template js and render it as a HTML using Java.
org.mozilla.javascript.EcmaError: TypeError: Cannot find function compile in object [object Object].
code snippet which i am trying to use is
File scriptFile = new File("./dust.js");
DustEngine DSE = new DustEngine( new FileInputStream(scriptFile));
DustEngine.compileTemplate("intro", "Hello {name}!");
Was able to by pass the initial issue, the reason for the above error was that i had not loaded the dust.js into the context, once that is done i was able to compile the template.js.
Now i am able to render the template but with no output. could you please let me know by seeing the below code what i had done wrong.
String renderScript =
"{ dust.render( name, JSON.parse(json) , function( err, data) { if(err) { writer.write(err);} else { writer.write( data );} } ); }";
renderScope.put("name", renderScope, name);
renderScope.put("writer", renderScope, writer);
renderScope.put("json", renderScope, json);
output = (String) dustEngineContext.evaluateString(renderScope,
renderScript,
"JDustCompiler",
0,
null);
return output;
I want to use consilidate.js for rendering dust partials to logically place templates in different folders. How do I do that? Here is information on consolidate module:
http://stackoverflow.com/questions/12489739/using-dustjs-linkedin-templates-in-node-js-and-express3-x
But I would like to implement same on server side using Rhino. How do I link consolidate.js with Rhino?
@vybs Is there a Gradle plugin for linkedin-dustjs available?
Looks like there isn't. In case anyone finds this useful, I went ahead and wrote one myself: https://github.com/davidzchen/gradle-dustjs-plugin
@vybs, is dustjs templating w/V8 is supported in java ? I dont find any links around it
@vybs - Is there a jsr-223 code (ScriptEngine, ScriptEngineFactory) for Dust JS ? or are there any plans for it ?
If not, can one create the same using the direction pointed out by your sample ?
Thanks
@vybs - with this solution, there's one global dust object in globalScope
shared by every thread that uses DustEngine.render()
, right?
If I'm rendering a large number of 'unique' templates (let's say millions), would the dust cache would get too if I used unique names? What's the best way to handle this scenario?
For any 'unique' template, I was considering always using a reused name like "UNIQUE-" + Thread.currentThread().getId()
and calling loadTemplate before rendering each time, but I wasn't sure if there was a better solution since the cache might get larger with lots of threads. This seems better than creating tons of global scopes and disposing of them each time though. I did try using the same name for all threads and did observe problems due to the shared global context between threads.
This is a special use case for personalized text vs rendering pages where templates would be reused and more finite. Thanks!
EDIT: Updated strategy for threading after finding that using the same name between threads was not safe
http://engineering.linkedin.com/frontend/client-side-templating-throwdown-mustache-handlebars-dustjs-and-more