Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fragile handling of json views for enum, and LocaldateTime #10525

Closed
4 tasks
woodmawa opened this issue Mar 8, 2017 · 12 comments
Closed
4 tasks

fragile handling of json views for enum, and LocaldateTime #10525

woodmawa opened this issue Mar 8, 2017 · 12 comments

Comments

@woodmawa
Copy link

woodmawa commented Mar 8, 2017

Thanks for reporting an issue for Grails framework, please review the task list below before submitting the
issue. Your issue report will be closed if the issue is incomplete and the below tasks not completed.

NOTE: If you are unsure about something and the issue is more of a question a better place to ask questions is on Stack Overflow (http://stackoverflow.com/tags/grails) or Slack (http://slack-signup.grails.org). DO NOT use the issue tracker to ask questions.

Task List

  • build standard new gradle project. (grails 3.2.6)
    1) install json views plugin and dependencies
    2) write restController for a domain object, domain object contains enumType, a map, and ref to user
    static  responseFormats = ["json", "xml"]

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

    def index() {
        List<Post> postList = Post.list([fetch:[user:"join",rating:"join"]])
        respond postList, view:'index'  //trigger the templating engine
    }
}

for a domain class like this

class Post implements Serializable {

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

    //LocalDateTime dateCreated  //json vieww 1.1.5 cant cope with localDateTime
    //LocalDateTime lastUpdated
    Date dateCreated
    Date 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"


    }
}
  3) setup url mappings for service `/api/posts (resources: postRest)`
  4) build json view for GET  'index' action (list of posts) 
file: index.gson (has three options only last one works)
model {
    List<Post> postList
}

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

file: _post.gson 

model {
    Post post
}

//json hal.render(post, [deep:true])
//json hal.render(post)
json {
    hal.links (post)
    comments post?.comments
    description post?.description
    rating "${post?.rating?.stars}"
    postedBy "${post?.user.username}"
    //java8 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MMM-dd")
    //java8 def when = post.dateCreated.format(formatter)
    SimpleDateFormat dateFormatter = new SimpleDateFormat ('yyyy-MMM-dd')
    def when = dateFormatter.format(post.dateCreated)
    created when
}

 5) set up test data in bootstrap.groovy
  6) invoke service from rest client.  If try `json hal.render(post, [deep:true])` or `json hal.render(post)` it stack dumps - (first this happened because i was using LocalDateTimes - and 1.1.5 doesnt handle that yet from another stackoverflow topic - so reduced the domain class back to just using Date), having cure that by reverting to Date, i tried the hal.render options and this dumps with 
  • Stacktrace
postRest:returning index action with model :  [org.softwood.Post : 1]
2017-03-08 14:09:43.558 ERROR --- [nio-8080-exec-3] o.g.web.errors.GrailsExceptionResolver   : StackOverflowError occurred when processing request: [GET] /api/guest/posts
Stacktrace follows:

java.lang.reflect.InvocationTargetException: null
	at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:210)
	at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:187)
	at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)

...
Caused by: grails.views.ViewRenderException: Error rendering view: null
	at grails.views.AbstractWritableScript.writeTo(AbstractWritableScript.groovy:43)
	at grails.plugin.json.view.api.internal.DefaultGrailsJsonViewHelper$8.writeTo(DefaultGrailsJsonViewHelper.groovy:790)
	at grails.plugin.json.view.JsonViewTemplate.json(JsonViewTemplate.groovy:126)
	at grails.plugin.json.view.JsonViewTemplate.json(JsonViewTemplate.groovy:149)
	at _info_app_name__postRest_index_gson.run(_info_app_name__postRest_index_gson:12)
	at grails.plugin.json.view.JsonViewTemplate.doWrite(JsonViewTemplate.groovy:35)
	at grails.views.AbstractWritableScript.writeTo(AbstractWritableScript.groovy:40)
	... 49 common frames omitted
Caused by: java.lang.StackOverflowError: null
	at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName(Class.java:264)
	at grails.plugin.json.builder.JsonOutput.writeObject(JsonOutput.java:328)
	at grails.plugin.json.builder.JsonOutput.writeIterator(JsonOutput.java:482)
	at grails.plugin.json.builder.JsonOutput.writeObject(JsonOutput.java:290)
lots of write object 

when it runs using the third option i get this which shows that the renderer is doing things, and my own translation of enum to String works as shown "rating":"5 star"

[
  {
"_links": {
"self": {
"href": "http://192.168.1.238:8080/post/show/1",
"hreflang": "en_GB",
"type": "application/hal+json"
}
},
"comments": {
"view": "lovely"
},
"description": null,
"rating": "FiveStar",
"postedBy": "will",
"created": "2017-Mar-08"
}
],
  • Github: example
  • Full description of the issue provided (see below)

Expected Behaviour

shouldn't break on standard types such as enum, LocalDateTime etc.

Actual Behaviour

loops and does stackoverflow , Once you get a stacktrace in dev cant seem to edit /fix and restest. have to restart the app to pick up corrections

Environment Information

  • Operating System: Windows 10
  • Grails Version: 3.2.6
  • JDK Version: java8 1.2.1
  • **Container Version (If Applicable):n/a

Example Application

@jameskleeh
Copy link
Contributor

This issue is not very clear and rather confusing because you are reporting multiple issues in a single report.

json views 1.1.x doesn't support java 8 date types

I'm not convinced the Rating domain class is causing any issues. If you can narrow down the issue with rating, and produce an example that doesn't complicate things with java8 date types, that would make this issue much more easily tackled.

Please file a new issue in https://github.com/grails/grails-views that only reports on the enum problem.

Thanks

@woodmawa
Copy link
Author

woodmawa commented Mar 8, 2017

James, i removed the LocalDateTime - i was focussed on reduced problem set. i have the domain class as shown, when i use `json hal.render(post) it fails as shown.

when i remove that and write my own view and convert the enum to string it worked fine as shown.

what more do you want to pare back to ?

@jameskleeh
Copy link
Contributor

Your example project still has the properties in the domain. There are no controllers or views in your example application

@woodmawa
Copy link
Author

woodmawa commented Mar 8, 2017 via email

@woodmawa
Copy link
Author

woodmawa commented Mar 8, 2017 via email

@woodmawa
Copy link
Author

woodmawa commented Mar 8, 2017 via email

@woodmawa
Copy link
Author

woodmawa commented Mar 8, 2017 via email

@jameskleeh
Copy link
Contributor

Provide steps to reproduce.

http://localhost:8080/api/posts responds with 401

@woodmawa
Copy link
Author

woodmawa commented Mar 8, 2017 via email

@woodmawa
Copy link
Author

woodmawa commented Mar 8, 2017 via email

@woodmawa
Copy link
Author

woodmawa commented Mar 8, 2017

james - theres a guest /api/guest/posts that skirts the grails security - if you try that you should see the error i get i hope

@jameskleeh
Copy link
Contributor

You're rendering a user object which has a LocalDate.

@grails grails locked and limited conversation to collaborators Mar 8, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants