Hi All
We are trying to execute handlebar templates via a Script Engine Inside AEM. This Handlebar Execution needs to done using the Rhino Script Engine as we don't want to go to with Java based execution in order to be flexible in future to replace handlebars with any other client side templating language. I am able to load the Rhino script Engine successfully and also able to evaluate the handlebar.js file using the engine. However when I am trying to obtain a"javax.script.Invocable" object from "org.apache.sling.scripting.javascript.internal.RhinoJavaScriptEngine" to call a JS method, I am getting below error.
Caused by: org.apache.sling.api.SlingException: Cannot get DefaultSlingScript: org.apache.sling.scripting.javascript.internal.RhinoJavaScriptEngine cannot be cast to javax.script.Invocable
at org.apache.sling.scripting.core.impl.DefaultSlingScript.service(DefaultSlingScript.java:481)
at com.day.cq.wcm.tags.IncludeTag.includeScript(IncludeTag.java:167)
at com.day.cq.wcm.tags.IncludeTag.doEndTag(IncludeTag.java:87)
at org.apache.jsp.apps.saks.components.testing.testing_jsp._jspx_meth_cq_005finclude_005f0(testing_jsp.java:178)
at org.apache.jsp.apps.saks.components.testing.testing_jsp._jspService(testing_jsp.java:152)
at org.apache.sling.scripting.jsp.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.sling.scripting.jsp.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:502)
It seems AEM has done the implementation of Rhino Engine in a different way as JDK because the same code runs fine as a Stand alone Java Program. Below is the code snippet being used to execute the handlebars as suggested on Java Scripting Programmer's Guide.
ScriptEngine engine = scriptEngineManager.getEngineByName("javascript");
URL fileURL = FrameworkUtil.getBundle(getClass()).getEntry("META-INF/js/handlebars.js");
try {
String jsSource = IOUtils.toString(fileURL.openStream());
engine.eval(jsSource);
} catch (IOException e) {
e.printStackTrace();
}
Object mustache = engine.eval("Handlebars");
String template = "Email addresses of {{contact.name}}:\n"
+ "{{#contact.emails}}\n" + "- {{.}}\n" + "{{/contact.emails}}";
Object compiledTemplate = invocable.invokeMethod(handlebar, "compile",template);
If anyone has done a similar thing using Rhino or any other JS Engine inside AEM, please help me identify the cause & solution to above problem.
Thanks
Nitin
Solved! Go to Solution.
Views
Replies
Total Likes
If you are just trying to do this from the scripting tier, you can do several other things:
For example, here's a Sightly JS Use object which uses Handlebars:
use(function () { load("/etc/clientlibs/granite/handlebars/source/handlebars.js"); var templateText = "Email addresses of {{contact.name}}:\n" + "{{#contact.emails}}\n" + "- {{.}}\n" + "{{/contact.emails}}"; var template = Handlebars.compile(templateText); return { output : template({contact : { name : 'foo', emails : [ 'a@a.com', 'b@b.com' ] } }) }; });
Of course in reality, you wouldn't want to hardcode the object like that :)
Views
Replies
Total Likes
I think you're going to have to post some code.
FWIW, it is true that RhinoJavaScriptEngine cannot be cast to Invocable. I guess the question is why you need to do this.
Views
Replies
Total Likes
Since you are invoking this from inside a JSP you might want to consider using the Java derivative, moustache.java. Rhino is much slower than compiled Java, so you'd get better performance if all you need is Moustache (with no modifications/extensions).
If your goal is specifically to get the Rhino engine working, you have to get the engine and pass your script in as a parameter. In this case it seems you are getting the Rhino engine but are mis-casting the object to something else. Can you provide us an example of the source code indicated in the stack trace where you are invoking Rhino?
Views
Replies
Total Likes
We don't want to do it using a Java bundle for handlebar as we want to have the flexibility of replacing handlebars with dust or react in future & although we have a Java based Processor for Handlebars (jknack) , not sure if we will have for other templating languages or not. We wanted to use Nashorn as the Script Engine for the same, but some I am even not able to get Nashorn working inside AEM (Please see http://help-forums.adobe.com/content/adobeforums/en/experience-manager-forum/adobe-experience-manage... ) so had to work with Rhino for the time being.
Views
Replies
Total Likes
Sorry I didn't pasted code in the issue itself. So, We are trying to execute handlebar templates inside AEM. We want to render these templates using a JS Engine, so if tomorrow we need to replace handlebar with other templating language as dust etc, we can do the same. I am able to load the Rhino script Engine successfully and also able to evaluate the handlebar.js file using the engine. However when I am trying to obtain a"javax.script.Invocable" object from "org.apache.sling.scripting.javascript.internal.RhinoJavaScriptEngine" to call a JS method, I getting this error.
ScriptEngine engine = scriptEngineManager.getEngineByName("javascript");
URL fileURL = FrameworkUtil.getBundle(getClass()).getEntry("META-INF/js/handlebars.js");
try {
String jsSource = IOUtils.toString(fileURL.openStream());
engine.eval(jsSource);
} catch (IOException e) {
e.printStackTrace();
}
Object mustache = engine.eval("Handlebars");
String template = "Email addresses of {{contact.name}}:\n"
+ "{{#contact.emails}}\n" + "- {{.}}\n" + "{{/contact.emails}}";
Object compiledTemplate = invocable.invokeMethod(handlebar, "compile",template);
Thanks
Nitin
Views
Replies
Total Likes
Right, that cast won't work. Is there somewhere you saw that it was documented?
Views
Replies
Total Likes
If you are just trying to do this from the scripting tier, you can do several other things:
For example, here's a Sightly JS Use object which uses Handlebars:
use(function () { load("/etc/clientlibs/granite/handlebars/source/handlebars.js"); var templateText = "Email addresses of {{contact.name}}:\n" + "{{#contact.emails}}\n" + "- {{.}}\n" + "{{/contact.emails}}"; var template = Handlebars.compile(templateText); return { output : template({contact : { name : 'foo', emails : [ 'a@a.com', 'b@b.com' ] } }) }; });
Of course in reality, you wouldn't want to hardcode the object like that :)
Views
Replies
Total Likes
Hi Justin,
This cast is from JDK docs it seems AEM hasn't implemented it in the same way as JDK has done.
http://docs.oracle.com/javase/7/docs/technotes/guides/scripting/programmer_guide/
Thanks
Nitin
Views
Replies
Total Likes
Oh, and BTW, there is already a community-based Handlebars ScriptEngine here: http://svn.apache.org/repos/asf/sling/whiteboard/ieb/handlebars
To me, the idea of replacing all your HBS templates with Dust seems like it is going to be a pain regardless of how you implement the template compilation.
Views
Replies
Total Likes
Hi Justin,
The engine @ http://svn.apache.org/repos/asf/sling/whiteboard/ieb/handlebars/ use jknack which is a java based implementation of handlebars. We have already used it for our Server Side Java based Execution. What we are trying to do here is Server Side JS Based Execution.
Thanks
Nitin
Views
Replies
Total Likes
Views
Likes
Replies