Spring Boot vs. Groovy Templates - Can't iterate over list inside ModelAndView
I am evaluating Spring Boot for a future application and would like to use Groovy templates for their sheer readable beauty. Unfortunately I am having problems repeating the list of objects that I add to the ModelAndView object returned from the controller.
This is my controller:
@RestController
@RequestMapping("/ships")
public class ShipsController {
@Autowired
ShipDao shipDao;
@RequestMapping(method = RequestMethod.GET)
public ModelAndView ships() {
final ModelAndView modelAndView = new ModelAndView("views/ships");
modelAndView.addObject("ships", this.shipDao.findAll());
return modelAndView;
}
}
And this is my template:
yieldUnescaped '<!DOCTYPE html>'
html(lang:'en') {
head {
meta('http-equiv':'"Content-Type" content="text/html; charset=utf-8"')
title('My page')
}
body {
p('Look at all these ships:')
ul {
ships.each { ship ->
li('$ship.name')
}
}
}
}
But all I can see in the browser is:
Look at all these ships:
$ ship.name
I was able to reassure myself that the list returned from the DAO contains three objects, but this seems to be ignored / not recognized by the template.
What also strikes me is that even if the courts are missing from the template, why does it even show one li element? I would not expect that in this case (empty list) or rather an error for a null object reference.
Anyone with an idea?
Edit
I just tried the same with Thymeleaf templates and it works like a charm. So these are not my controllers.
Maybe you can only use Groovy templates with Groovy and not Java?
source to share
I had the same problem with groovy templates. It looks like groovy's templating engine is wrapping your templating code in a temporary class named after the template file. In your case, it creates a class named ships
and that class name hides your model attribute. So ships.each{...}
trying to iterate over the type instance Class<ships>
.
You can either rename the model attribute or use spring implicit RequestContext attribute like spring.model.ships.each{...}
source to share