I am a newbie at Groovy and I want to modify one example I’ve found at the Internet (the blog one).
I’ve defined two classes Post and Comment as follows:
class Post {
static hasMany = [comments:Comment]
String title
String teaser
String content
Date lastUpdated
SortedSet comments
static constraints = {
title(nullable:false, blank:false, length:1..50)
teaser(length:0..100)
content(nullable:false, blank:false)
lastUpdated(nullable:true)
}
String toString() {title}
}
Post post
String comment
String name
String url
String email
Date dateCreated = new Date()
static belongsTo = Post
static constraints = {
comment(nullable:false, blank:false)
name(nullable:false, blank:false)
url(nullable:true, blank:true, url:true)
email(nullable:true, blank:true, email:true)
dateCreated(nullable:true)
post(nullable:false)
}
public int compareTo(Object o) {
return dateCreated.compareTo(o.dateCreated)
}
String toString() {comment}
}
Up to now all OK.
I’ve defined the controllers as follows:
class CommentController {
def edit = {
render(view:'edit',
model:[ comment:new Comment(),
postId:params.postId])
}
def save = {
def comment = new Comment(params)
comment.dateCreated = new Date()
comment.post = Post.get(params.postId)
if(comment.save()) {
redirect(
controller:'post',
action:'list',
id:params.postId)
}
}
}
class PostController {
def defaultAction = 'list'
def index = {
render("En el norte de Alabama")
}
def edit = {
render(view:'edit', model:[post:loadPost(params.id)])
}
def save = {
def post = loadPost(params.id)
post.lastUpdated = new Date()
post.properties = params
if(post.save()) {
print "id " + post.id + "\n"
def offset = post.id - 1
print "offset " + offset
redirect(action:'list', offset:offset)
} else {
render(view:'edit', model:[post:post])
}
}
def list = {
if(!params.max)params.max = 1
[ postList: Post.list( params ) ]
}
def view = {
render(view:'view', model:[post:Post.get(params.id)])
}
private loadPost(id) {
def post = new Post();
if(id) {
post = Post.get(id)
}
return post
}
}
Finally I’ve defined the views/post/list
as follows:
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head><title>My postList</title>
</head>
<body>
<div class="nav">
<g:link controller="post" action="edit">New post</g:link>
</div>
<span class="menuButton"><H1>Last posts</H1></span>
<table border = 1><tr><td>
<g:each in="${postList}" var="post">
<div>
<h2>${post.title}</h2>
<p>Last update: <g:formatDate date="${post.lastUpdated}"
format="yyyy-MMM-dd HH:mm"/></p>
<p><i>${post?.content}</i></p>
</div>
<div class="paginateButtons">
<g:link controller="comment" action="edit" params="[postId:post.id]">
Add comment
</g:link>
</div>
<g:each in="${post.comments}" var="comt">
${comt.comment} <br />
</g:each>
</g:each>
<td></tr></table>
<div class="paginateButtons">
<g:paginate max="1" next="Next" prev="Prev."
total="${postCount == null ? Post.count(): postCount}" />
</div>
</body>
</html>
I can generate new Posts without any problem, but when I want to put comments to my posts I can put at most ONE comment for each post. When trying to put more I get a ClassCastException as follows:
Message: Comment
Caused by: Error processing GroovyPageView: Comment
Class: /WEB-INF/grails-app/views/post/list.gsp
At Line: [-1]
org.codehaus.groovy.grails.web.pages.exceptions.GroovyPagesException: Error processing GroovyPageView: Comment
at org.codehaus.groovy.grails.web.servlet.view.GroovyPageView.handleException(GroovyPageView.java:134)
at org.codehaus.groovy.grails.web.servlet.view.GroovyPageView.renderWithTemplateEngine(GroovyPageView.java:112)
at org.codehaus.groovy.grails.web.servlet.view.GroovyPageView.renderMergedOutputModel(GroovyPageView.java:86)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:257)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1183)
at org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet.doDispatch(GrailsDispatcherServlet.java:294)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1124)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:70)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:70)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:334)
at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:126)
at org.codehaus.groovy.grails.web.util.WebUtils.forwardRequestForUrlMappingInfo(WebUtils.java:293)
at org.codehaus.groovy.grails.web.util.WebUtils.forwardRequestForUrlMappingInfo(WebUtils.java:269)
at org.codehaus.groovy.grails.web.util.WebUtils.forwardRequestForUrlMappingInfo(WebUtils.java:261)
at org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter.doFilterInternal(UrlMappingsFilter.java:181)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter.obtainContent(GrailsPageFilter.java:171)
at org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter.doFilter(GrailsPageFilter.java:110)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.codehaus.groovy.grails.web.servlet.filter.GrailsReloadServletFilter.doFilterInternal(GrailsReloadServletFilter.java:101)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:65)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:534)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:864)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:533)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:207)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:403)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:522)
Caused by: java.lang.ClassCastException: Comment
at java.util.TreeMap.compare(TreeMap.java:1093)
at java.util.TreeMap.put(TreeMap.java:465)
at java.util.TreeSet.add(TreeSet.java:210)
at java.util.AbstractCollection.addAll(AbstractCollection.java:318)
at java.util.TreeSet.addAll(TreeSet.java:258)
at D__Workspace_groovypublish_grails_app_views_post_list_gsp$_run_closure5.doCall(D__Workspace_groovypublish_grails_app_views_post_list_gsp:52)
at D__Workspace_groovypublish_grails_app_views_post_list_gsp.run(D__Workspace_groovypublish_grails_app_views_post_list_gsp:21)
Seems to be that the problem is at the list.gsp file when trying to put nested “each”s
Any hint
Thanks in advance
Luis
Well, from what I can read here, you’re using SortedSet as your container type for Comments in a Post. This is fine, but you have to make Comments implement Comparable, as that’s a requirement for all SortedSet-contained objects. You’d probably want your comments sorted by dateCreated anyway, so you have to SAY that somewhere (like in the compareTo function you’ll need to satisfy the interface).
Any reason you’re not just using a List? Seems like you wouldn’t want to add Comments with earlier dates anyway.
Anyway, if this isn’t it, comment and I’ll take a longer look.