web-dev-qa-db-fra.com

Impossible d'initialiser le proxy - pas de session

J'ai une erreur qui ressemble à ceci:

Impossible d'initialiser le proxy - pas de session

Je travaille avec Java, hibernate et spring. Cette erreur apparaît lorsque vous essayez de générer un document PDF, et je suis les étapes suivantes pour le générer à la volée et le stocker dans la base de données.

  1. J'ai envoyé une demande à l'application via une méthode POST. Cela génère le PDF à la volée et montre à l'utilisateur).

  2. Juste après cette demande j'en envoie une autre, mais via un ajax une demande. Cela générera le même PDF mais l'enregistrera dans la base de données.

L'erreur montre qu'une requête n'a pas pu être exécutée en raison de l'erreur "impossible d'initialiser le proxy - pas de session".

Y a-t-il quelque chose que je fais mal, appelant deux fois les mêmes méthodes à partir de la même session utilisateur? Se pourrait-il que la session soit fermée avant la fin des deux demandes?

J'espère que quelqu'un pourra m'aider à comprendre ce qui se passe.

29
Misael P

Votre problème est que la session d'hibernation ne vit que pour une seule demande. Il s'ouvre au début de la demande et se ferme à la fin. Vous avez deviné la réponse: la session de mise en veille prolongée est fermée avant la fin des deux demandes.

Que se passe-t-il exactement? Vos objets d'entité sont actifs pendant les deux requêtes. Comment? Ils sont stockés dans la session HTTP (qui est une chose différente appelée session). Vous ne donnez pas beaucoup d'informations sur le framework que vous utilisez, donc je ne peux pas vous donner plus de détails, mais il est certain que le framework que vous utilisez conserve en quelque sorte vos entités dans la session HTTP. C'est ainsi que le framework vous permet de travailler facilement avec les mêmes objets pour plusieurs requêtes.

Lorsque le traitement de la deuxième demande démarre, le code tente d'accéder à une entité (généralement un élément d'une collection) qui est paresseusement initialisée par hibernate. L'entité n'est pas attachée à une session d'hibernation, et donc hibernate ne peut pas initialiser le proxy hibernate avant de le lire. Vous devez ouvrir une session et y rattacher votre entité au début du traitement de la demande ajax.

MODIFIER:

Je vais essayer de donner une brève explication de ce qui se passe derrière la scène. Tous Java ont un ou plusieurs servlets qui gèrent les requêtes. Le servlet gère chaque requête (HttpRequest) en créant un nouveau thread qui produira finalement la réponse (HttpResponse). La méthode qui traite chaque demande est exécutée à l'intérieur de ce fil.

Au début du traitement de la demande, votre application doit allouer les ressources dont elle a besoin pour le traitement (Transaction, session Hibernate, etc.). À la fin du cycle de traitement, ces ressources sont libérées (la transaction est validée, la session de mise en veille prolongée est fermée, les connexions JDBC sont libérées, etc.). Le cycle de vie de ces ressources pourrait être géré par votre infrastructure ou être effectué par votre code.

Afin de prendre en charge l'état d'application dans un protocole sans état comme HTTP, nous avons l'objet HttpSession. Nous (ou les frameworks) mettons sur HttpSession les informations qui restent pertinentes entre les différents cycles de demande d'un même client.

Pendant le traitement de la première requête, hibernate lit (paresseusement) une entité de la base de données. En raison de l'initialisation paresseuse, certaines parties de la structure de cet objet sont des objets proxy d'hibernation. Ces objets sont associés à la session de mise en veille prolongée qui les a créés.

Le framework recherche l'entité de la requête précédente dans l'objet HttpSession lorsque vous essayez de traiter la deuxième requête. Ensuite, il essaie d'accéder à une propriété à partir d'une entité enfant qui a été initialisée paresseusement et qui est maintenant un objet proxy de mise en veille prolongée. L'objet proxy hibernate est une imitation de l'objet réel qui demandera à sa session hibernate de le remplir avec les informations de la base de données lorsque quelqu'un essaie d'accéder à l'une de ses propriétés. C'est ce que votre proxy hibernate essaie de faire. Mais sa session a été fermée à la fin du traitement de la demande précédente, donc il n'a plus de session d'hibernation à utiliser pour être hydraté (rempli d'informations réelles).

Notez qu'il est possible que vous ayez déjà ouvert une session de mise en veille prolongée au début de la deuxième demande, mais qu'il ne connaît pas l'entité qui contient l'objet proxy car cette entité a été lue par une session d'hibernation différente. Vous devez rattacher l'entité à la nouvelle session de mise en veille prolongée.

Il y a beaucoup de discussions sur la façon de rattacher une entité détachée, mais l'approche la plus simple en ce moment est session.update(entity).

J'espère que ça aide.

69
nakosspy