0

I'm trying out JSON views, not on top of domain class using @Resource, but by creating a RestfulController and trying to render that using JSON views. I've added all the relevant dependencies in build config.

I have a domain Post class like this (which I didn't want to directly expose)

class Post implements Serializable {

    Map comments
    User user
    Venue venue
    String description
    Rating rating       //should this be an enum?

    LocalDateTime dateCreated
    LocalDateTime lastUpdated

    static belongsTo = [user:User]
    static hasOne = [rating:Rating]

    static constraints = {
        venue   nullable:true
        comments nullable:true
        description nullable:true

        rating  nullable:true, lazy:false
    }

    static mapping = {
        //set the sort order for Posts -  default using newest post first
        sort dateCreated :"desc"


    }
}

So I then created a default RestfulController like this:

class PostRestController extends RestfulController {
    static  responseFormats = ["json", "xml"]

    //constructor - tells rest controller which domain class to scaffold
    PostRestController() {
        super (Post)
    }
}

I'm not overriding any of the default scaffolding methods here.

When I used a rest client to access the default (I've mapped /api/posts (resources: postRest in the UrlMappings). When I access the URL with my REST client I got the full dump of the Post (including comments field persisted in a map) - this looks like this in my rest client - all OK:

[
  {
"id": 1,
"comments": {
"view": "lovely"
},
"dateCreated": {
"class": "java.time.LocalDateTime",
"dayOfMonth": 7,
"dayOfWeek": {
"enumType": "java.time.DayOfWeek",
"name": "TUESDAY"
},
"dayOfYear": 66,
"hour": 19,
"minute": 15,
"month": {
"enumType": "java.time.Month",
"name": "MARCH"
},
"monthValue": 3,
"nano": 263000000,
"second": 10,
"year": 2017,
"chronology": {
"calendarType": "iso8601",
"class": "java.time.chrono.IsoChronology",
"id": "ISO"
}
},
"description": null,
"lastUpdated": {
"class": "java.time.LocalDateTime",
"dayOfMonth": 7,
"dayOfWeek": {
"enumType": "java.time.DayOfWeek",
"name": "TUESDAY"
},
"dayOfYear": 66,
"hour": 19,
"minute": 15,
"month": {
"enumType": "java.time.Month",
"name": "MARCH"
},
"monthValue": 3,
"nano": 263000000,
"second": 10,
"year": 2017,
"chronology": {
"calendarType": "iso8601",
"class": "java.time.chrono.IsoChronology",
"id": "ISO"
}
},
"rating": null,
"user": {
"id": 1
},
"venue": null
}
],

I then tried to add JSON views on top of this in the grails-app/views/postRest folder.

I did a really simple template _post.gson like this:

model {
    Post post
}

json {
    comments post.comments
    description post.description
    //rating post.rating
    userWhoPosted "${post?.user}"
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MMM-dd")
    def when = post.dateCreated.format(formatter)
    created when
}

I then added an index.gson to render the template:

model {
    List<Post> postList
}

//call the template to iterate over the postList to produce the output
json g.render(postList)

This breaks the server with this stacktrace and a 500 error to the REST client. If I comment out the line in_post.gson relating to user it all works. Leave it in and it fails:

Caused by: grails.views.ViewRenderException: Error rendering view: null
    at grails.views.AbstractWritableScript.writeTo(AbstractWritableScript.groovy:43)
    at grails.views.mvc.GenericGroovyTemplateView.renderMergedOutputModel(GenericGroovyTemplateView.groovy:73)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
    at grails.views.mvc.renderer.DefaultViewRenderer.render(DefaultViewRenderer.groovy:111)
    at grails.artefact.controller.RestResponder$Trait$Helper.internalRespond(RestResponder.groovy:188)
    at grails.artefact.controller.RestResponder$Trait$Helper.respond(RestResponder.groovy:62)
    at grails.rest.RestfulController.index(RestfulController.groovy:64)
    at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
    ... 4

If I comment out the post.user (and ratings reference) it works OK, but when I try and post the post.user it fails with the above. There was a note in the docs about ensuring that your query pulled the refs with a fetch join - so I tried to provide a override to ensure I returned the fetch join - all I get is empty returned to the client:

class PostRestController extends RestfulController {
    static  responseFormats = ["json", "xml"]

    //constructor - tells rest controller which domain class to scaffold
    PostRestController() {
        super (Post)
    }

    def index() {
        Collection<Post> res = Post.list([fetch:[user:"join",rating:"join"]])
        res
    }
}

Why when I do it without the JSON view it works fine and when I use the JSON view I can't get the output including references? I checked the list request and it returns the list successfully in the debugger - but breaks in the rendering.

If I can get this to work, JSON views on Grails 3.2.6 looks pretty nice.

halfer
  • 19,824
  • 17
  • 99
  • 186
WILLIAM WOODMAN
  • 1,185
  • 5
  • 19
  • 36

1 Answers1

2

Aaargh - think this issue is with jsonViews 1.1.5 - its not ready for java 8 LocalDateTime.

i saw a trace on stackoverflow see topic

hibernate will now take localdateTime in your domain classes - that works. But the json template rendering wont, even if you add the java8 plugin.

So i went back into domain class changed my LocalDateTime back to Date, also changed the json template to use the older SimpleDateTime format (instead of DateTimeFormatter) and re ran - low and behold it worked.

I'll be really glad when we can say grails is properly java8 ready.

apparently json views requires feature enablement which is due in json views 2 (think this is an M2 right now) - so i've had to revert to java 7 Date until then.

blimey another lost day in the weeds.

Community
  • 1
  • 1
WILLIAM WOODMAN
  • 1,185
  • 5
  • 19
  • 36