Using precompiled templates with embedded scalate

529 views
Skip to first unread message

Scott Clasen

unread,
Mar 3, 2011, 3:38:06 PM3/3/11
to Scalate
I am investigating using scalate in an embedded fashion, and want to
use precompiled templates.

Currently I have the maven-scalate-plugin bound to the process-classes
phase so that I can write a unit test that executes the compiled
templates.

However when I write a test like so, the test blows up during Template
compilation, which I was expecting not to happen at all. Perhaps I am
using the wrong uri?

@Test
def evalTestTemplate() {
val engine = new TemplateEngine(None, "production")
engine.boot
val ctx = Map("foo" -> "test123")
val result: String = engine.layout("/scalate/test.ssp", ctx)
System.out.println(result)
}

So question is how do I "make" the template use the precompiled
template that is in my classpath?

Hiram Chirino

unread,
Mar 3, 2011, 4:13:59 PM3/3/11
to sca...@googlegroups.com, Scott Clasen
Could you post your error, or better yet post a small mvn project
demonstrating the issue?


Regards,
Hiram

FuseSource
Web: http://fusesource.com/

Scott Clasen

unread,
Mar 3, 2011, 4:36:43 PM3/3/11
to Scalate
Here is the template which is in src/resources/scalate/test.ssp

<%@ val foo:String %>
<p>${foo}</p>

Here is the plugin def, I see the generated sources in target/
generated-sources, and the compiled templates in target/classes
as well as seeing the plugin execute
<plugin>
<groupId>org.fusesource.scalate</groupId>
<artifactId>maven-scalate-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>compile</id>
<phase>process-classes</phase>
<goals>
<goal>precompile</goal>
</goals>
<configuration>
<warSourceDirectory>${basedir}/src/main/resources/
scalate</warSourceDirectory>
</configuration>
</execution>
</executions>
</plugin>


Here is the excepton, which leads me to believe some compilation is
going on...I was hoping not to need a dependency on scala-compiler..

org.fusesource.scalate.TemplateException: scala/tools/nsc/settings/
ScalaSettings
at
org.fusesource.scalate.TemplateEngine.compileAndLoad(TemplateEngine.scala:
775)
at
org.fusesource.scalate.TemplateEngine.compileAndLoadEntry(TemplateEngine.scala:
637)
at
org.fusesource.scalate.TemplateEngine.liftedTree1$1(TemplateEngine.scala:
368)
at org.fusesource.scalate.TemplateEngine.load(TemplateEngine.scala:
362)
at org.fusesource.scalate.TemplateEngine.load(TemplateEngine.scala:
420)
at org.fusesource.scalate.TemplateEngine.layout(TemplateEngine.scala:
521)
at ScalateTesting.evalTestTemplate(ScalateTesting.scala:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:
641)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:677)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:850)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1154)
at
org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:
137)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:
121)
at org.testng.TestRunner.runWorkers(TestRunner.java:1108)
at org.testng.TestRunner.privateRun(TestRunner.java:737)
at org.testng.TestRunner.run(TestRunner.java:596)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:315)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:310)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:272)
at org.testng.SuiteRunner.run(SuiteRunner.java:221)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1027)
at org.testng.TestNG.runSuitesLocally(TestNG.java:964)
at org.testng.TestNG.run(TestNG.java:896)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:89)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:144)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:
115)
Caused by: java.lang.NoClassDefFoundError: scala/tools/nsc/settings/
ScalaSettings
at org.fusesource.scalate.support.ScalaCompiler
$.create(ScalaCompiler.scala:39)
at
org.fusesource.scalate.TemplateEngine.compiler(TemplateEngine.scala:
194)
at
org.fusesource.scalate.TemplateEngine.compileAndLoad(TemplateEngine.scala:
691)
... 36 more

I will work on the mvn project example...

Hiram Chirino

unread,
Mar 3, 2011, 5:03:53 PM3/3/11
to sca...@googlegroups.com
Sorry.. that should have been
System.setProperty("scalate.allowReload", "false")

Regards,
Hiram

FuseSource
Web: http://fusesource.com/


On Thu, Mar 3, 2011 at 5:03 PM, Hiram Chirino <hi...@hiramchirino.com> wrote:
> Yep it's trying to compile it.  The question is what does your test
> class path look like and does it contain that compiled template
> classes?  Is it just an issue of the engine thinking the templates
> have gone stale and trying to compile it again?  Try doing
> System.setProperty("scalate.allowReload", "true") before you run your
> test.

Hiram Chirino

unread,
Mar 3, 2011, 5:03:29 PM3/3/11
to sca...@googlegroups.com
Yep it's trying to compile it. The question is what does your test
class path look like and does it contain that compiled template
classes? Is it just an issue of the engine thinking the templates
have gone stale and trying to compile it again? Try doing
System.setProperty("scalate.allowReload", "true") before you run your
test.


Regards,
Hiram

FuseSource
Web: http://fusesource.com/

scott clasen

unread,
Mar 3, 2011, 5:21:52 PM3/3/11
to sca...@googlegroups.com, Hiram Chirino
Ok, that helps....it finds the compiled templates!

Now a new issue...can precompiled templates only be used in a webapp?
the gen'ed code is trying to use servletRenderContext/

java.lang.ClassCastException:
org.fusesource.scalate.DefaultRenderContext cannot be cast to
org.fusesource.scalate.servlet.ServletRenderContext
at scalate.$_scalate_$test_ssp$.$_scalate_$render(test.ssp.scala:10)
at scalate.$_scalate_$test_ssp.render(test.ssp.scala:27)
at org.fusesource.scalate.layout.NullLayoutStrategy$.layout(LayoutStrategy.scala:43)
at org.fusesource.scalate.TemplateEngine$$anonfun$layout$1.apply(TemplateEngine.scala:503)
at org.fusesource.scalate.TemplateEngine$$anonfun$layout$1.apply(TemplateEngine.scala:503)
at org.fusesource.scalate.RenderContext$.using(RenderContext.scala:49)
at org.fusesource.scalate.TemplateEngine.layout(TemplateEngine.scala:503)
at org.fusesource.scalate.TemplateEngine.layout(TemplateEngine.scala:535)
at org.fusesource.scalate.TemplateEngine.layout(TemplateEngine.scala:522)
at ScalateTesting.evalTestTemplate(ScalateTesting.scala:21)


at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)

scott clasen

unread,
Mar 3, 2011, 5:25:31 PM3/3/11
to sca...@googlegroups.com, Hiram Chirino
Here is the gened source

/* NOTE this file is autogenerated by Scalate : see
http://scalate.fusesource.org/ */
package scalate

import _root_.scala.collection.JavaConversions._
import _root_.org.fusesource.scalate.support.TemplateConversions._

object $_scalate_$test_ssp {
def $_scalate_$render($_scalate_$_context:
_root_.org.fusesource.scalate.RenderContext): Unit = {
;{
implicit val context:
_root_.org.fusesource.scalate.servlet.ServletRenderContext =
$_scalate_$_context.attribute("context")
import context._


;{
val foo: String = $_scalate_$_context.attribute("foo")
$_scalate_$_context << ( "<p>" );
$_scalate_$_context <<< ( foo
);
$_scalate_$_context << ( "</p>" );
}
}
}
}


class $_scalate_$test_ssp extends _root_.org.fusesource.scalate.Template {
def render(context: _root_.org.fusesource.scalate.RenderContext):
Unit = $_scalate_$test_ssp.$_scalate_$render(context)

scott clasen

unread,
Mar 3, 2011, 5:26:26 PM3/3/11
to sca...@googlegroups.com, Hiram Chirino
This is line 10 if its hard to tell

implicit val context:
_root_.org.fusesource.scalate.servlet.ServletRenderContext =
$_scalate_$_context.attribute("context")

Wille Faler

unread,
Mar 3, 2011, 5:31:42 PM3/3/11
to sca...@googlegroups.com
This seems to be a confirmed bug in pre-compilation: had exactly the same question from another person on the Bowler Framework list where he saw ClassCastExceptions.

Should pre-compilation really make such bold assumptions about the type of RenderContext that is being used? 

scott clasen

unread,
Mar 3, 2011, 5:37:51 PM3/3/11
to sca...@googlegroups.com, Wille Faler
I think I just figured it out.

The Precompiler defaults to ServletRenderContext, if you dont specify
a contextClass in the maven plugin.

Specifying this is what I tried,

<contextClass>org.fusesource.scalate.DefaultRenderContext</contextClass>

And I get the output im looking for

scott clasen

unread,
Mar 3, 2011, 5:40:24 PM3/3/11
to sca...@googlegroups.com, Wille Faler
Here is the full plugin config that worked...

<plugin>
<groupId>org.fusesource.scalate</groupId>
<artifactId>maven-scalate-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>compile</id>
<phase>process-classes</phase>
<goals>
<goal>precompile</goal>
</goals>
<configuration>

<resourcesSourceDirectory>${basedir}/src/main/resources/scalate</resourcesSourceDirectory>
<contextClass>org.fusesource.scalate.DefaultRenderContext</contextClass>
</configuration>
</execution>
</executions>
</plugin>

Hiram Chirino

unread,
Mar 3, 2011, 5:40:43 PM3/3/11
to sca...@googlegroups.com
Ah good catch. I think it's a sensible default since Scalate's most
common use case is to render web pages.


Regards,
Hiram

FuseSource
Web: http://fusesource.com/

Hiram Chirino

unread,
Mar 3, 2011, 5:41:12 PM3/3/11
to sca...@googlegroups.com
Nice! Good job.

Regards,
Hiram

FuseSource
Web: http://fusesource.com/

Jozef Dransfield

unread,
Mar 3, 2011, 5:42:23 PM3/3/11
to sca...@googlegroups.com
Sorry i hit the wrong button....

any idea how to set that contextClass in sbt?

-- 
Jozef Dransfield
Sent with Sparrow

On Thursday, 3 March 2011 at 22:41, Jozef Dransfield wrote:

Any idea how to set that 

-- 
Jozef Dransfield
Sent with Sparrow

scott clasen

unread,
Mar 3, 2011, 5:51:45 PM3/3/11
to sca...@googlegroups.com, Jozef Dransfield
I would guess something like

def precompilerContextClass = Some("other.context.class.Name") in
your sbt project, assuming you are already using the compiler

Hiram Chirino

unread,
Mar 3, 2011, 5:53:06 PM3/3/11
to sca...@googlegroups.com
Right, but with an override:

override def precompilerContextClass = Some("other.context.class.Name")

Regards,
Hiram

FuseSource
Web: http://fusesource.com/

James Strachan

unread,
Mar 4, 2011, 2:33:09 AM3/4/11
to sca...@googlegroups.com
I wonder if the absence of the scala-compiler should behave as if
reload is disabled? I hit this yesterday, getting
ClassNotFoundException trying to load the scala compiler - even though
I had already precomplied the templates.

--
James
-------
FuseSource
Email: ja...@fusesource.com
Web: http://fusesource.com
Twitter: jstrachan
Blog: http://macstrac.blogspot.com/

Open Source Integration

Hiram Chirino

unread,
Mar 4, 2011, 8:01:10 AM3/4/11
to sca...@googlegroups.com
Yeah.. Good point. Also, I thought that in "production" mode
reloading was supposed to be disabled. Don't think it is.


Regards,
Hiram

FuseSource
Web: http://fusesource.com/

Scott Clasen

unread,
Mar 4, 2011, 9:25:06 AM3/4/11
to sca...@googlegroups.com, sca...@googlegroups.com
+1

Sent from my iPhone

James Strachan

unread,
Mar 4, 2011, 9:26:40 AM3/4/11
to sca...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages