Rendering lists from Google AppEngine as JSON


I ran into another problem with Google AppEngine. I finally got it to save my entities, only to find it crashing as I wanted to send them back again rendered as JSON.

I had a piece of code looking like this:

def services = {
 params.max = Math.min(params.max ? params.max.toInteger() : 10, 100)
 render Offering.list(params) as JSON;
 }

The code is simple enough, it loads all the Service offerings using GORM and then renders them as JSON using the built in converter. This resulted in the following error:

Uncaught exception from servlet
org.codehaus.groovy.runtime.InvokerInvocationException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Error converting Bean with class org.codehaus.groovy.reflection.ClassLoaderForClassArtifacts
...
Caused by: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Error converting Bean with class org.codehaus.groovy.reflection.ClassLoaderForClassArtifacts
	at grails.converters.JSON.value(JSON.java:199)
	at grails.converters.JSON.convertAnother(JSON.java:156)
...
	at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_$3.run(Method_.java:149)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_.privilegedInvoke(Method_.java:147)
	at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_.invoke(Method_.java:120)
	... 26 more
Caused by: java.lang.reflect.InvocationTargetException
	at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_$3.run(Method_.java:149)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_.privilegedInvoke(Method_.java:147)
	at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_.invoke(Method_.java:120)
...
Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission getClassLoader)
	at java.security.AccessControlContext.checkPermission(Unknown Source)
	at java.security.AccessController.checkPermission(Unknown Source)
	at java.lang.SecurityManager.checkPermission(Unknown Source)
	at java.lang.ClassLoader.getParent(Unknown Source)
	... 59 more

The problem is that the GORM loads the class with some meta data attached to it. I’m not allowed to reflect over this meta data, so the normal converter fails with the above error. I took the privilege to shorten the stack trace somewhat.

The work around is simple and elegant. I use the groovy collection method called select. With this I can construct a list with maps with the fields I want in my JSON and render them using the normal converter.

def services = {
 params.max = Math.min(params.max ? params.max.toInteger() : 10, 100)
 def list =  Offering.list(params);
 render list.collect { offering->[id:offering.id, name:offering.name]} as JSON
 }

The above code works fine on Google AppEngine.

I hope this helps someone else.

Bookmark and Share

, ,

  1. #1 by Morten on November 24, 2010 - 08:25

    Great feedback, thanks!

  2. #2 by Cem GÜLER on November 24, 2010 - 09:23

    Thx for the post, that saved some time. However, while using gorm-jpa, this will be the correct render statement unless you want to render the Key field as JSON:

    render list.collect { offering->[id:offering.id.id, name:offering.name]} as JSON

    and id field should be declared as com.google.appengine.api.datastore.Key in the domain class.

    Anyways, thx again :)

(will not be published)