juin
2009
Le cloud computing offre des avantages certains et celui de GAE facilite le déploiement d’application Java comme jamais.
En ne m’occupant pas de l’infrastructure sous-jacente, je pense gagner le temps que je passerai à résoudre des problèmes réseaux et/ou matériel.
Ceci dit, lorsque que votre application fonctionne bien en local mais pas sur GAE, vous vous posez des questions ?
Ce billet se veut l’exemple d’un problème plus général que je nomme le syndrôme de l’outil magique ou de la boite noire.
Je teste une petite application qui met des données en session (un User) mais une fois déployée, elle ne fonctionne plus ???
Après investigation, je me rend compte que mon objet User n’est pas enregistré dans ma session HTTP côte serveur. Comment cela se fait t’il ?
Je me suis d’abord dit qu’il fallait peut être mon objet User soit une entité JDO/JPA puisque j’avais lu que la persistance des sessions GAE utilisait le datastore.
Je n’étais pas très convaincu mais j’ai pris l’habitude de n’écarter aucune piste même celle qui nous semble la plus improbable (à cause de la loi de Murphy).
Mon problème n’étant pas résolu après avoir rendu mon entité capable de persistance, j’ai essayé d’enregistrer dans ma session une variable de type simple et là, ça ne fonctionnait toujours pas ?
En traçant un peu (il n’y a pas de déboguage distant), je me suis rendu compte que j’avais bien mon objet User dans ma session lorsqu’il est placé par ma requête N mais qu’il n’était plus dans ma session lorsque j’essaye d’y accéder par ma requête N+1.
- J’avais lu quelque part que si plusieurs JVM peuvent servir votre application, un utilisateur connecté (session créée) reste toujours sur la même JVM ?
- D’après une autre source, j’ai également lu que dans GAE, il n’est pas garantie que la requête N+1 soit servie par la même JVM que la requête N.
Les différentes JVM où tournent votre application se partagent donc la session d’un utilisateur ?
Comme vous pouvez vous en rendre compte, ces deux informations sont contradictoires.
Quoiqu’il en soit, je ne pense pas que la répartition de charge se mette en place dès la première petite application déployée ? Le problème ne pouvait donc à priori pas venir d’une execution sur deux JVM différentes ?
Néanmoins, la deuxième source expliquait également que les attributs mis en session par session.setAttribute() étaient sérialisés et c’est ce qui m’a permis d’identifier mon problème.
Il faut savoir que pour différentes raisons, je ne place pas directement mes attributs de session dans la session HTTP mais par l’intermédiaire d’une Map.
Je met donc une Map dans la session (utilisation de setAttribute()) et ensuite je met mes objets de session dans cette Map.
- Avec l’implémentation classique des sessions, il n’est pas nécessaire de « remettre » cette Map en session à chaque ajout d’un paramètre dans ma Map car la session pointe vers ma Map.
- Dans GAE, lorsque je met ma Map dans la session, ce n’est pas mon objet Map qui est mis dans la session mais sa sérialisation sous forme d’octets. Or, comme à cet instant, elle est vide, tant que je ne réactualise pas cette Map dans la session par un nouvel appel à setAttribute, les paramètres mis dans ma Map sont perdus dès que se termine ma requête.
J’ai ainsi résolu mon problème en enregistrant ma Map de session juste avant de retourner la réponse au lieu de le faire juste après la réception de la requête.
Dans cette histoire, mon problème venait de ma façon de faire : modifier le contenu d’un objet mis en session (ma Map).
Je ne reproche à GAE ni son implémentation (c’est peut être moi qui ne respecte pas le contrat des sessions), ni son absence de documentation (elle existe peut être et je ne l’ai pas trouvé).
Ce que je critique, c’est qu’on soit obligé de comprendre le fonctionnement à l’intérieur de la boite noire ! Certes, c’est toujours intéressant mais cela nous fait perdre du temps qu’on était censé économiser.
Vous pouvez venir en débattre sur ce forum dédié à mes billets GAE ou sur celui-ci plus général.