Spring MVC controller with Scalate view resolver returning NoValueSetException

523 views
Skip to first unread message

Tristan

unread,
Dec 17, 2010, 5:06:23 PM12/17/10
to Scalate
I'm learning Scala/Scalate and I'm trying to convert an existing
Spring MVC webapp to use scalate templates with scaml. The problem I'm
running into is that objects that are added to the model in the
controller are not accessible in the view (I get the
NoValueSetException).

I'm using a org.fusesource.scalate.spring.view.ScalateViewResolver for
the view resolver in my spring config and pages are rendered.

The controller method is pretty simple:
@RequestMapping(value = "/user", method = RequestMethod.GET)
protected String listAllUsers(final Model model) {
Collection<User> users = userService.listUsers();
model.addAttribute("users", users);
return "/WEB-INF/scala/user.scaml"
}

"/WEB-INF/scala/user.scaml" is this:
!!! 5
%html(lang="en")
%head
%meta(charset="utf-8")
%body
%div.row
%section.col.col_12.content
%article#users
-@ val users: java.util.Collection[com.x.y.User]
- collection(users, "index", separator = "<br/>")
%div.clear(style="height:10px; border-bottom:1px solid #ccc;")
%footer.row

If I assign a default List() to user 'users' everything works OK. Am I
missing something (maybe it's just my lack of experience with scala/
scalate)?

Thanks,
Tristan

Stefan Ollinger

unread,
Dec 17, 2010, 7:54:15 PM12/17/10
to Scalate
Hi,

i ran into the same problem.
After looking into the scalate-spring-mvc code, it seems the model
handling is a bit strange.
The model is set to "it", if you check out:
https://github.com/scalate/scalate/blob/master/scalate-spring-mvc/src/main/scala/org/fusesource/scalate/spring/view/ScalateView.scala

I dont know if it is supposed to be like this and i also didnt manage
to get eclipse with full scala debug support working.
Maybe someone with a bit more insight could comment on this.

Greets,
Stefan

James Strachan

unread,
Dec 20, 2010, 6:33:38 AM12/20/10
to sca...@googlegroups.com

The current Spring MVC support uses a similar approach to JAXRS /
Servlets - taking the default model and mapping it to the 'it'
attribute. Though if there's a different way you'd like to map things
it should be trivial to support other approaches.

e.g. we could expose each entry in Spring MVC's model Map as
attributes in the template.

Do you fancy tweaking the Spring MVC classes to suit your needs and
submitting a patch?

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

Open Source Integration

Tristan Burch

unread,
Dec 20, 2010, 12:51:02 PM12/20/10
to sca...@googlegroups.com
Thanks James. I'll make a patch once I'm able to get it working with the "it" attribute.

If I change my controller to work like the sample one (in Java instead of Scala):

@RequestMapping(value = "/user", method = RequestMethod.GET)

protected ModelAndView listAllUsers(final Model model) {

Collection<User> users = userService.listUsers();

ModelAndView mv = new ModelAndView(viewName("/WEB-INF/scala/user.scaml", true));

mv.addObject("it", users);

return mv;

}

I still get the "No 'it' model object specified. Cannot render request" exception. When debugging, I see "it" in the ModelAndView before I leave the controller. Shouldn't this work?

Thanks,
Tristan

James Strachan

unread,
Dec 20, 2010, 12:54:22 PM12/20/10
to sca...@googlegroups.com
If you comment out the 'it' attribute definition in your template (or
provide a default expression for the it attribute value), then expand
the Scalate console, you can see all the attributes available to
Scalate. It might be interesting looking at what attributes are
available and their types. I wonder if 'it' is defined and if so what
type of value is it?

Stefan Ollinger

unread,
Dec 22, 2010, 3:08:49 AM12/22/10
to Scalate
After digging through the rendering code i solved my problems.
The trick is that you need to add a "render:" prefix in front of the
template name to be rendered.
With that, the scalate-spring-mvc chooses the
DefaultScalateRenderStrategy, which publishes all model
attributes inside the template.

The controller:

@Controller
@RequestMapping("/scalate")
public class ScalateController {
@RequestMapping("test")
public String test(Model model) {
model.addAttribute("aStr", "100");
model.addAttribute("aInt", 21387);
model.addAttribute("someObject", new SomeObject());
return "render:scamlTest.scaml";
}
}

The SomeObject class:

package sample;

public class SomeObject {
public String a = "The first string";
public String b = "The second string";
}

The scamlTest.scaml template looks like this:

-@ val aStr : String = attributes("aStr").asInstanceOf[String]
-@ val aint : Int = attributes("aInt").asInstanceOf[Int]
-@ val someObject: sample.SomeObject =
attributes("someObject").asInstanceOf[sample.SomeObject]

string: #{aStr}
int: #{aInt} (#{aint.asInstanceOf[AnyRef].getClass()})
someObject: #{someObject}
someObject->a: #{someObject.a}
someObject->b: #{someObject.b}

I wonder if the typecasting is needed at the beginning or if there is
a more simple way. Maybe via generics.

Another problem is that you cant use the ScalateViewResolver together
with the
org.springframework.web.servlet.view.InternalResourceViewResolver.
So you have to choose between jsp and scalate and can not use both
together.

Spring MVC does have the option to chain multiple ViewResolvers.
Spring goes tthrough the chain one after another, until one view
resolver can render the template.

When a resolver is unable to render the template, it needs to return
null from loadView(..). Unfortunately InternalResourceViewResolver can
never return null,
because of the way it handles the render process. ScalateViewResolver
now also doesnt return null in case there is no template found. In
fact it tries to render
the template, which leads to this exception:

org.springframework.web.util.NestedServletException: Request
processing failed; nested exception is
org.fusesource.scalate.TemplateException: Template file extension
missing. Cannot determine which template processor to use.

Maybe it would be sufficient to add a simple check if the template
file exists:
https://github.com/scalate/scalate/blob/master/scalate-spring-mvc/src/main/scala/org/fusesource/scalate/spring/view/ScalateViewResolver.scala#L27
What do you think?

Greets, Stefan

On 20 Dez., 18:54, James Strachan <james.strac...@gmail.com> wrote:
> If you comment out the 'it' attribute definition in your template (or
> provide a default expression for the it attribute value), then expand
> the Scalate console, you can see all the attributes available to
> Scalate. It might be interesting looking at what attributes are
> available and their types. I wonder if 'it' is defined and if so what
> type of value is it?
>
> On 20 December 2010 17:51, Tristan Burch <m...@tristanburch.com> wrote:
>
>
>
> > Thanks James. I'll make a patch once I'm able to get it working with the
> > "it" attribute.
> > If I change my controller to work like the sample one (in Java instead of
> > Scala):
>
> > @RequestMapping(value = "/user", method = RequestMethod.GET)
>
> > protected ModelAndView listAllUsers(final Model model) {
>
> > Collection<User> users = userService.listUsers();
>
> > ModelAndView mv = new ModelAndView(viewName("/WEB-INF/scala/user.scaml",
> > true));
>
> > mv.addObject("it", users);
>
> > return mv;
>
> > }
>
> > I still get the "No 'it' model object specified. Cannot render request"
> > exception. When debugging, I see "it" in the ModelAndView before I leave the
> > controller. Shouldn't this work?
> > Thanks,
> > Tristan
> > On Mon, Dec 20, 2010 at 3:33 AM, James Strachan <james.strac...@gmail.com>
> > wrote:
>
> >> On 18 December 2010 00:54, Stefan Ollinger <Stefan.Ollin...@gmx.de> wrote:
> >> > Hi,
>
> >> > i ran into the same problem.
> >> > After looking into the scalate-spring-mvc code, it seems the model
> >> > handling is a bit strange.
> >> > The model is set to "it", if you check out:
>
> >> >https://github.com/scalate/scalate/blob/master/scalate-spring-mvc/src...

Stefan Ollinger

unread,
Dec 22, 2010, 3:13:41 AM12/22/10
to Scalate
Reading the documentation sometimes helps =)

No need to cast the attributes:

-@ val test : String
-@ val aint : Int
-@ val someObject: com.dots42.shop.backend.web.SomeObject
> file exists:https://github.com/scalate/scalate/blob/master/scalate-spring-mvc/src...

James Strachan

unread,
Dec 22, 2010, 3:29:10 AM12/22/10
to sca...@googlegroups.com
On 22 December 2010 08:08, Stefan Ollinger <Stefan....@gmx.de> wrote:
> After digging through the rendering code i solved my problems.
> The trick is that you need to add a "render:" prefix in front of the
> template name to be rendered.
> With that, the scalate-spring-mvc chooses the
> DefaultScalateRenderStrategy, which publishes all model
> attributes inside the template.

Thanks for a great example! More inline...


> The controller:
>
> @Controller
> @RequestMapping("/scalate")
> public class ScalateController {
>        @RequestMapping("test")
>        public String test(Model model) {
>                model.addAttribute("aStr", "100");
>                model.addAttribute("aInt", 21387);
>                model.addAttribute("someObject", new SomeObject());
>                return "render:scamlTest.scaml";
>        }
> }
>
> The SomeObject class:
>
> package sample;
>
> public class SomeObject {
>        public String a = "The first string";
>        public String b = "The second string";
> }
>
> The scamlTest.scaml template looks like this:
>
> -@ val aStr : String = attributes("aStr").asInstanceOf[String]
> -@ val aint : Int = attributes("aInt").asInstanceOf[Int]
> -@ val someObject: sample.SomeObject =
> attributes("someObject").asInstanceOf[sample.SomeObject]

Note that you don't need to use the right hand assignment part above.
When you use the syntax...

-@ val aStr : String

that actually maps to code roughly equal to...

- val aStr : String = attributes[String]("aStr")

which is a helper method for the code you wrote...

- val aStr : String = attributes("aStr").asInstanceOf[String]

So really all the -@ syntax does is allow you to automatically bind
attributes to named parameters in a more concise DRY way. Plus it lets
you define optional values if there is no attribute defined. e.g.

-@val aStr: String = "some default"

is syntax sugar for

- val aStr : String = attributeOrElse[String]("aStr", "some default")


> int: #{aInt} (#{aint.asInstanceOf[AnyRef].getClass()})
> someObject: #{someObject}
> someObject->a: #{someObject.a}
> someObject->b: #{someObject.b}
>
> I wonder if the typecasting is needed at the beginning or if there is
> a more simple way. Maybe via generics.

Yeah, see above - I thought I'd reply under a specific line so its
easier to compare the differences.


> Another problem is that you cant use the ScalateViewResolver together
> with the
> org.springframework.web.servlet.view.InternalResourceViewResolver.
> So you have to choose between jsp and scalate and can not use both
> together.

Shame; wonder if there's a way around it? Though ditching all JSP
everywhere is quite a pleasing moment :)


> Spring MVC does have the option to chain multiple ViewResolvers.
> Spring goes tthrough the chain one after another, until one view
> resolver can render the template.
>
> When a resolver is unable to render the template, it needs to return
> null from loadView(..). Unfortunately InternalResourceViewResolver can
> never return null,
> because of the way it handles the render process. ScalateViewResolver
> now also doesnt return null in case there is no template found. In
> fact it tries to render
> the template, which leads to this exception:
>
> org.springframework.web.util.NestedServletException: Request
> processing failed; nested exception is
> org.fusesource.scalate.TemplateException: Template file extension
> missing. Cannot determine which template processor to use.
>
> Maybe it would be sufficient to add a simple check if the template
> file exists:
> https://github.com/scalate/scalate/blob/master/scalate-spring-mvc/src/main/scala/org/fusesource/scalate/spring/view/ScalateViewResolver.scala#L27
> What do you think?

Sounds great! Then could Scalate go first in the chain; then if it
can't find the template it returns null and lets the next one in the
chain render it?

Thanks for the feedback!

We should definitely improve the Spring MVC samples & docs!

Tristan Burch

unread,
Dec 28, 2010, 12:51:11 PM12/28/10
to sca...@googlegroups.com
I submitted a pull request that adds support for order, prefix and suffix on the ScalateViewResolver: https://github.com/scalate/scalate/pull/3

I can also submit some samples and docs. Where is the best place to do this?

-Tristan

Hiram Chirino

unread,
Dec 28, 2010, 2:39:04 PM12/28/10
to sca...@googlegroups.com
Both documentation and examples go into the project git repo. You can
start a new documentation page under:

scalate-website/src/main/webapp/documentation

See the jog.page for an example of a framework documentation page.

and the examples should go under samples/scalate-sample-spring-mv


Regards,
Hiram

FuseSource
Web: http://fusesource.com/

Jérôme

unread,
Dec 29, 2010, 5:44:42 AM12/29/10
to Scalate
I starting testing the a java Spring MVC controler with scalate
templating,
and I was little confused, by passing the model to the view

with (No templating system)
@RequestMapping("test")
public String test(Model model) {
model.addAttribute("aStr", "100");
return "render:scamlTest.scaml";
}
With attribute is available in the page like that
-@ val aStr : String

But with a controler that use a LayoutScalateRenderStrategy (without
prefix render) like
@RequestMapping("test")
public String test(Model model) {
model.addAttribute("aStr", "100");
return "/scamlTest.scaml";
}
The same attribute it not available
The value for 'aStr' was not set</pre></p><h3>Caused by:</
h3><pre>org.fusesource.scalate.NoValueSetException


In watching the code of the ScalateView in opposite of the
DefaultScalateRenderStrategy (selected by rendered)
cf https://github.com/scalate/scalate/blob/master/scalate-spring-mvc/src/main/scala/org/fusesource/scalate/spring/view/ScalateView.scala

The model seem to be lost because it not past to the
templateEngine.layout

trait LayoutScalateRenderStrategy extends AbstractTemplateView with
ScalateRenderStrategy {
def templateEngine:ServletTemplateEngine
def render(context:ServletRenderContext, model: Map[String,Any]) {
templateEngine.layout(getUrl, context)
}
}



And need to add the model to the evaluation of the template
something like that
templateEngine.layout(getUrl, context, model )

I am wrong or that it is more that a lack of documentation,
I mean a bug in Spring Mvc integration ?

Stefan Ollinger

unread,
Dec 29, 2010, 11:39:30 AM12/29/10
to sca...@googlegroups.com
Hello J�r�me,

it looks to me that layouts are not meant to receive a model, but rather
take care on how the final layout of the website will look like. That
means you pass the model to a render template and this render template
to layout again. If you need to use attributes inside the layout, you
declare them in the layout template and assign them in the render
template. Check the documentation at:
http://scalate.fusesource.org/documentation/user-guide.html#layouts

Greets,
Stefan

Jérôme

unread,
Jan 3, 2011, 8:18:08 AM1/3/11
to Scalate
Hello Stefan,

Thank for this anwser but

I try to say, that in the file index.scaml, (that it is completed by
the template /scalate/layout/default.scaml)
The model is not accessible in this main file (named in this case
index.scaml).

And with the same Spring MVC controler, (just by changing the renderer
mode from LayoutScalateRenderStrategy to DefaultScalateRenderStrategy
thank the using of the prefix url render) the model is readable and
not throw the NoValueSetException

I don't understand this difference of behaviour,


In watching the code in org.fusesource.scalate.spring.view package, I
see that
1* DefaultScalateRenderStrategy use the model by calling the method
context.render(getUrl, model)
2* LayoutScalateRenderStrategy lose the model because using the
method templateEngine.layout(getUrl, context)

Not using in 2* the model parameter.

That could explain that the model is not transfered to the main page
with the LayoutScalateRenderStrategy.
Should I open a bug for this ?
or how to read this model with LayoutScalateRenderStrategy ?

because I really not understand,


Thank you by advance

Greets,

Jérôme




James Strachan

unread,
Jan 4, 2011, 10:17:07 AM1/4/11
to sca...@googlegroups.com
On 28 December 2010 17:51, Tristan Burch <m...@tristanburch.com> wrote:
> I submitted a pull request that adds support for order, prefix and suffix on
> the ScalateViewResolver: https://github.com/scalate/scalate/pull/3

patches all applied now with huge thanks!

Jérôme

unread,
Jan 5, 2011, 4:49:00 PM1/5/11
to Scalate
Thank for this true improvement

One think stange

This syntax work
<bean
class="org.fusesource.scalate.spring.view.ScalateViewResolver"
p:cache="false">
<property name="order" value="1"/>
<property name="prefix" value="/WEB-INF/scalate/"/>
<property name="suffix" value=".scaml"/>
</bean>


But this syntax with p namespace do Not work
<bean
class="org.fusesource.scalate.spring.view.ScalateViewResolver"
p:order="1"
p:prefix="/WEB-INF/scalate/"
p:suffix=".scaml"
p:cache="false" />

The properties was not set in ScalateViewResolver
except for the cache properties that was correctly set in the
AbstractCachingViewResolver

The BeanProperty annotation don't read the p:namespace ?

Tristan Burch

unread,
Jan 5, 2011, 7:59:16 PM1/5/11
to sca...@googlegroups.com
Hi Jérôme,

I just tried out the following spring config and everything seems to work as expected. Do you have any other view resolvers configured?

<bean class="org.fusesource.scalate.spring.view.ScalateViewResolver" p:order="1" p:prefix="/WEB-INF/views/scalate/" p:suffix=".jade" p:cache="false" />


Cheers,
Tristan

Jérôme

unread,
Jan 6, 2011, 7:13:09 AM1/6/11
to Scalate
A InternalViewResolver,
The only difference between the 2 configurations is this spring
declaration with p namaspace,

I will make a patch for sample project in order to illustrated a
little more the Scalate Spring MVC Integration in a Java Project
I could be a good sample for projects that would migrated to scala

And in an other hand,
I could be a way to show my other problem of reading model variable in
LayoutScalateRenderStrategy (now with layout: prefix )

James Strachan

unread,
Jan 6, 2011, 7:14:15 AM1/6/11
to sca...@googlegroups.com
On 6 January 2011 12:13, Jérôme <jmor...@gmail.com> wrote:
> A InternalViewResolver,
> The only difference between the 2 configurations is this spring
> declaration with p namaspace,

Do you have a full example with the namespace declaration BTW?

> I will make a patch for  sample project in order to illustrated a
> little more the Scalate Spring MVC Integration in a Java Project
> I could be a good sample for projects that would migrated to scala

Great stuff!

Jérôme

unread,
Jan 7, 2011, 1:17:51 PM1/7/11
to Scalate
Hi James,


I do a sample that could be get from : https://github.com/jmorille/scalate.git

My sample as fork is here
https://github.com/jmorille/scalate/tree/master/samples/scalate-sample-spring-mvc-java

To run it, like you're sample, In the folder scalate-sample-spring-mvc-
java, and just run
* mvn jetty:run
* And go to the page http://127.0.0.1:8080/index.html

This sample show 2 problems

1* The p:namespace configuration
(Just switch the conf in comment in the dispatch-servlet.xml and do
a jetty:run )
and go to the index.html page that not working now because
* The layout parameter is not set, and in concequence it don't
find the scaml files
* The p:cache=false, show that is read by the java part but not
by scala.

2* The NoValueSetException error of model reading in
LayoutScalateRenderStrategy (original subject of this thread)
In the body of the index page of this sample
- The link n°1 : The reading of the model with
DefaultScalateRenderStrategy, that work find but with no decoration
tamplate
- The link n°2 : The reading of the model with
LayoutScalateRenderStrategy , that Not work
The only difference between the 2 code is the prefix layout: ...


Regards,

Jérôme



On 6 jan, 13:14, James Strachan <ja...@fusesource.com> wrote:

Stefan Ollinger

unread,
Jan 10, 2011, 4:22:05 PM1/10/11
to sca...@googlegroups.com
Hi Jérôme,

ok, i think i know what you mean.

In your example:
https://github.com/jmorille/scalate/blob/master/samples/scalate-sample-spring-mvc-java/src/main/java/org/fusesource/scalate/sample/springmvcjava/controller/ModelController.java#L23

Does the readingModelData expose the model into the template or do you get a NoValueSetException?

Greets,
Stefan

Stefan Ollinger

unread,
Jan 10, 2011, 4:58:52 PM1/10/11
to sca...@googlegroups.com
The problem is, that the LayoutScalateRenderStrategy does not pass the
model to the RenderContext.
I created a fix:
https://github.com/dozed/scalate/commit/dcbc6be7527a26009b08865054ed002654ada600

James: Maybe there is a better way to do this?

Greets,
Stefan

> J�r�me


>
>
>
> On 6 jan, 13:14, James Strachan<ja...@fusesource.com> wrote:

Stefan Ollinger

unread,
Jan 10, 2011, 5:09:25 PM1/10/11
to sca...@googlegroups.com
One cool thing you can do now, is change the layout with:

@RequestMapping("layout")
public String layout(Model model) {
model.addAttribute("layout", "/WEB-INF/scalate/layouts/special.scaml");
return "layout:views/foo";
}

This one uses now layouts/special.scaml instead of layouts/default.scaml =)

Greets,
Stefan

Jérôme

unread,
Jan 11, 2011, 4:52:48 AM1/11/11
to Scalate
Thank you for this patch and this tips
I will test this tomorow,

Did you succes to reproduce the String p:namespace properties setting
problem ?



On 10 jan, 23:09, Stefan Ollinger <Stefan.Ollin...@gmx.de> wrote:
> One cool thing you can do now, is change the layout with:
>
> @RequestMapping("layout")
> public String layout(Model model) {
>      model.addAttribute("layout", "/WEB-INF/scalate/layouts/special.scaml");
>      return "layout:views/foo";
>
> }
>
> This one uses now layouts/special.scaml instead of layouts/default.scaml =)
>
> Greets,
> Stefan
>
> Am 10.01.2011 22:58, schrieb Stefan Ollinger:
>
> > The problem is, that the LayoutScalateRenderStrategy does not pass the
> > model to the RenderContext.
> > I created a fix:
> >https://github.com/dozed/scalate/commit/dcbc6be7527a26009b08865054ed0...
>
> > James: Maybe there is a better way to do this?
>
> > Greets,
> > Stefan
>
> > Am 07.01.2011 19:17, schrieb J r me:
> >> Hi James,
>
> >> I do a sample that could be get from  :
> >>https://github.com/jmorille/scalate.git
>
> >> My sample as fork is here
> >>https://github.com/jmorille/scalate/tree/master/samples/scalate-sampl...
>
> >> To run it, like you're sample, In the folder scalate-sample-spring-mvc-
> >> java, and  just run
> >>   * mvn jetty:run
> >>   * And go to the pagehttp://127.0.0.1:8080/index.html

Stefan Ollinger

unread,
Jan 11, 2011, 8:02:28 AM1/11/11
to sca...@googlegroups.com
Yes, i can reproduce the problem with the p: syntax.

Do you have a link to spring's documentation about this syntax? Looks
like it is a shortcut for <property ..> and is handled differently by
spring than the property tags. Maybe there is something written in the docs.

Jérôme

unread,
Jan 11, 2011, 1:39:37 PM1/11/11
to Scalate

Stefan Ollinger

unread,
Jan 11, 2011, 1:47:51 PM1/11/11
to sca...@googlegroups.com
Hello J�r�me,

Please check this version:
https://github.com/dozed/scalate/commit/f4fc1fcaa2ba93267cf6901880f6767b3099182c

It works for me with the following xml configuration:

<bean class="org.fusesource.scalate.spring.view.ScalateViewResolver"
p:order="1"

p:cache="false"
p:prefix="/WEB-INF/scalate/"
p:suffix=".scaml" />

Greets,
Stefan

Stefan Ollinger

unread,
Jan 11, 2011, 2:07:06 PM1/11/11
to sca...@googlegroups.com
There is a typo in your dispatcher-servlet.xml:

xmlns:p=" http://www.springframework.org/schema/p"

Maybe remove the space and check again.

Greets,
Stefan

Jérôme

unread,
Jan 12, 2011, 7:47:41 AM1/12/11
to Scalate
1# In the p:namespace declaring if I suppress the space caractere
before, it working
This caracter is a problem for scala bean but not for spring bean
but anyway it a mistake in declaration and p:namespace work now

2# For the value set in layoutRender it work find, with you re patch
I will test the layout tip definition

3# In continuation of this sample, I starting the test with
ScalatePackage.scala variable definition
like doc say http://scalate.fusesource.org/documentation/user-guide.html#dry
I commited in my samples
This should work in WEB-INF/scalate directory ? because it don't
work ?



Reply all
Reply to author
Forward
0 new messages