2010-06-09 5 views
8

J'essaie de convertir un objet en JSON à l'aide de la bibliothèque GSON sur Google App Engine. Pour une raison quelconque, il jette cette exception et je ne comprends pas comment résoudre ce problème. Aucune suggestion?GSON sur Google App Engine déclenche une exception de sécurité

java.lang.SecurityException: java.lang.IllegalAccessException: Reflection is not allowed on private static final int java.util.BitSet.ADDRESS_BITS_PER_WORD 
    at com.google.appengine.runtime.Request.process-8d5b435d6736643f(Request.java) 
    at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:29) 
    at com.google.gson.ObjectNavigator.navigateClassFields(ObjectNavigator.java:141) 
    at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:123) 
    at com.google.gson.JsonSerializationVisitor.getJsonElementForChild(JsonSerializationVisitor.java:148) 
    at com.google.gson.JsonSerializationVisitor.addAsArrayElement(JsonSerializationVisitor.java:139) 
    at com.google.gson.JsonSerializationVisitor.visitArray(JsonSerializationVisitor.java:83) 
    at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:109) 
    at com.google.gson.JsonSerializationVisitor.getJsonElementForChild(JsonSerializationVisitor.java:148) 
    at com.google.gson.JsonSerializationVisitor.addAsChildOfObject(JsonSerializationVisitor.java:126) 
    at com.google.gson.JsonSerializationVisitor.visitArrayField(JsonSerializationVisitor.java:95) 
    at com.google.gson.ObjectNavigator.navigateClassFields(ObjectNavigator.java:154) 
    at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:123) 
    at com.google.gson.JsonSerializationContextDefault.serialize(JsonSerializationContextDefault.java:56) 
    at com.google.gson.Gson.toJsonTree(Gson.java:230) 
    at com.google.gson.Gson.toJson(Gson.java:315) 
    at com.google.gson.Gson.toJson(Gson.java:270) 
    at com.google.gson.Gson.toJson(Gson.java:250) 
    at companionmodel.Sample_Model_PopulateServlet.printOutput(Sample_Model_PopulateServlet.java:59) 
    at companionmodel.Sample_Model_PopulateServlet.doGet(Sample_Model_PopulateServlet.java:28) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:693) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:806) 
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) 
    at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:97) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) 
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 
    at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:238) 
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
    at org.mortbay.jetty.Server.handle(Server.java:326) 
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) 
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923) 
    at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76) 
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
    at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:135) 
    at com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:250) 
    at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:5838) 
    at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:5836) 
    at com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest(BlockingApplicationHandler.java:24) 
    at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:398) 
    at com.google.net.rpc.impl.Server$2.run(Server.java:852) 
    at com.google.tracing.LocalTraceSpanRunnable.run(LocalTraceSpanRunnable.java:56) 
    at com.google.tracing.LocalTraceSpanBuilder.internalContinueSpan(LocalTraceSpanBuilder.java:576) 
    at com.google.net.rpc.impl.Server.startRpc(Server.java:807) 
    at com.google.net.rpc.impl.Server.processRequest(Server.java:369) 
    at com.google.net.rpc.impl.ServerConnection.messageReceived(ServerConnection.java:442) 
    at com.google.net.rpc.impl.RpcConnection.parseMessages(RpcConnection.java:319) 
    at com.google.net.rpc.impl.RpcConnection.dataReceived(RpcConnection.java:290) 
    at com.google.net.async.Connection.handleReadEvent(Connection.java:474) 
    at com.google.net.async.EventDispatcher.processNetworkEvents(EventDispatcher.java:831) 
    at com.google.net.async.EventDispatcher.internalLoop(EventDispatcher.java:207) 
    at com.google.net.async.EventDispatcher.loop(EventDispatcher.java:103) 
    at com.google.net.rpc.RpcService.runUntilServerShutdown(RpcService.java:251) 
    at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run(JavaRuntime.java:413) 
    at java.lang.Thread.run(Unknown Source) 

code J'utilise:

Gson gson = new Gson(); 
String json = gson.toJson(modelObject); 
+1

Cette fonctionnalité de réflexion peut ne pas être disponible sur App Engine. Il est étrange, cependant, que AccessibleObject soit listé dans la liste blanche JRE: http://code.google.com/appengine/docs/java/jrewhitelist.html –

+0

@Jason: Merci pour la réponse. Cela veut dire que j'ai besoin d'écrire mes propres méthodes toJSON :( – Legend

+2

Reflection est disponible sur App Engine - mais il semble que cet objet particulier soit inaccessible, même si la bibliothèque essaie même d'y accéder. un BitSet sur JSON? –

Répondre

3

Le moteur app ne soutenir la réflexion - mais vous essayez de réfléchir sur un champ privé d'une classe JRE:

Réflexion

Une application est autorisée pleine, un accès illimité, réfléchissant à sa propres classes. Il peut interroger tous les membres privés , utiliser java.lang.reflect.AccessibleObject.setAccessible(), et lire/définir des membres privés.

Une application peut également refléter aussi sur les classes de l'API et JRE, tels que java.lang.String et javax.servlet.http.HttpServletRequest. Cependant, il ne peut accéder au public membres de ces classes, pas protégé ou privé.

Une application ne peut pas refléter contre les autres classes n'appartenant à lui-même, et il ne peut pas utiliser la méthode setAccessible() pour contourner ces restrictions.

... de http://code.google.com/appengine/docs/java/runtime.html#The_Sandbox:

Je considère l'écriture d'un sérialiseur personnalisé pour Bitset.

Voir: http://sites.google.com/site/gson/gson-user-guide#TOC-Custom-Serialization-and-Deserializ

aussi: http://groups.google.com/group/google-gson/browse_thread/thread/535892ffcf691aa/897f27e37e03ce58?lnk=gst&q=bitset#897f27e37e03ce58

http://groups.google.com/group/google-gson/browse_thread/thread/535892ffcf691aa

+0

Merci Dans mon cas, je ne suis pas sûr pourquoi GSON fait ce qu'il fait :) Si vous connaissez d'autres façons de le faire fonctionner , ça serait génial. – Legend

+0

Pas de wukkas. Peut-être regisiter un sérialiseur personnalisé pour Bitset? –

+0

Merci pour la suggestion. Je vais regarder dedans. – Legend

0

Si App Engine ne prend pas en charge la réflexion, alors nous sommes à peu près à gauche pour écrire notre propre méthode de toJSON. Cela peut se faire comme suit (pas une grosse affaire, mais quelqu'un pourrait trouver utile):

public SampleObject { 

    //... 

    /** 
    * Convert this object to a JSON object for representation 
    */ 
    public JSONObject toJSON() { 
    try { 
     JSONObject jsonobj = new JSONObject(); 
     jsonobj.put("id", this.id); 
     jsonobj.put("name", this.name); 
     return jsonobj; 
    } catch(Exception e) { 
     return null; 
    } 
    } 
} 

Ensuite, vous pouvez utiliser une méthode toString sur cet objet pour imprimer la représentation JSON. Pas le meilleur, je suis d'accord, mais une solution de contournement pour le moment.

1

Vous pouvez construire GsonBuilder avec .excludeFieldsWithoutExposeAnnotation(), et marquer tous les champs avec un numéro de série annotation @Expose. Dans ce cas, Gson n'essaie pas de sérialiser les champs que vous voulez.

GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.excludeFieldsWithoutExposeAnnotation(); 
String json = gsonBuilder.create().toJson(modelObject); 
0

J'ai récemment rencontré un problème similaire.

Je courais Gson pour analyser JSON et cela a bien fonctionné pendant une longue période, donc je n'ai pas craint que GAE ne permette pas Reflection sur sa plate-forme.

J'ai introduit une classe HashMap Form et cela a bien fonctionné dans mon système local avec Gson faisant JSON Parse parfaitement.

Mais quand je déployé ce code à Google App Cloud Engine il a échoué à l'exception suivante:

java.lang.SecurityException: java.lang.IllegalAccessException: Reflection is not allowed on private final int java.lang.ThreadLocal.threadLocalHashCode 

Alors maintenant, je suis passé à Jackson JSON Parser qui est plus rapide et ne pas utiliser la réflexion - mais oui - plus de travail.