Bean session sans état avec variables d'instance
J'ai un bean session sans état qui contient une méthode publique, plusieurs méthodes privées, et certains niveau de l'instance variables. Ci-dessous est un exemple de pseudo-code.
private int instanceLevelVar
public void methodA(int x) {
this.instanceLevelVar = x;
methodB();
}
private void methodB() {
System.out.println(instanceLevelVar);
}
Ce que je vois, c'est que methodB est l'impression des valeurs qui n'étaient pas passés dans MethodA. Du mieux que je peux dire c'est de l'impression des valeurs d'autres instances de la même bean. Ce qui serait à l'origine?
Je me dois de souligner que le code fonctionne comme prévu 99,9% du temps. Cependant, la .01% est à l'origine de sérieux problèmes /préoccupations pour moi.
Je comprends que si j'avais les différentes méthodes publiques alors je risque de ne pas obtenir les mêmes bean retour entre les appels, ce qui aurait pour résultat de ce comportement. Toutefois, dans ce cas, le seul appel est à la seule méthode publique. Sera le conteneur (Glassfish dans ce cas) encore échangez les haricots entre les appels de méthode?
(edit) j'ai renommé "le niveau de la classe" à "niveau de l'instance", comme cela a provoqué une certaine confusion.
source d'informationauteur Preston
Vous devez vous connecter pour publier un commentaire.
Je voudrais juste ne pas déranger à l'aide de variable d'instance de bean session sans état. Peu importe ce que la cause du problème que vous avez rencontré, c'est probablement pas quelque chose que vous voulez faire de toute façon. Simplement essayer d'utiliser des variables locales à travers, ou de définir des variables d'instance dans les classes d'aide vous appelez de la stateless session bean méthodes d'affaires.
Quand j'ai lu Qu'est ce qu'un Bean de Session? section de l'J2EE 1.4 tutoriel:
Dans votre cas, l'appel à
methodB()
demethodA()
sera sur la même instance et est équivalent àthis.methodB()
. Je suis donc tendance à dire quemethodB()
ne pouvez pas sortir autre chose que la valeur que ce qui a été transmis àmethodA()
.Ceci est confirmé par la première phrase de l'article 7.11.8 dans le EJB 2.0 spec: "Le conteneur doit s'assurer qu'un seul thread peut exécuter une instance à tout moment". Cela signifie que vous ne pouvez pas venir à une situation où les données (dans les variables d'instance) à partir de différents clients (threads) sera mélangé. Vous êtes assuré d'accès unique pour les variables d'instance jusqu'à ce que
methodA()
est de retour!Cela dit, je ne dis pas que vous n'avez pas un problème quelque part. Mais je ne pense pas que votre pseudo-code est équivalent.
(EDIT: après Avoir lu quelques commentaires à l'OP de la question, il est maintenant clairement un doute sur le pseudo-code et de la sémantique utilisée. Je suis clarifier les conséquences possibles ci-dessous.)
Comme l'a souligné Fusée Chirurgien, qu'entendez-vous exactement par variable de classe? Pensez-vous vraiment dire variable de classe par opposition à variable d'instance? Si oui, le code de pseudo ne reflète pas, mais ce sera bien évidemment entraîner un comportement imprévisible. En fait, à partir de la section 24.1.2 (et le premier point) dans l'EJB 2.0 spec, il est clair que vous n'êtes pas autorisé à écrire des données à une variable de classe (bien que vous pouvez le faire). Il doit y avoir une bonne raison pour cela 🙂
La cause probable du problème est que le conteneur est d'utiliser le même objet dans deux demandes (donc deux threads) en même temps. Ainsi, le premier fil est à la ligne qui appelle methodB et puis le prochain thread obtient le code qui appelle methodB et puis le premier thread qui exécute l'appel à methodB, à l'origine du problème. Qui pourrait expliquer le comportement, en tout cas. Il ne semble pas s'adapter à la spec, mais qui pourrait tout simplement être un bug.
En général, même si elle est autorisée, à conserver l'état de la fève n'est pas une bonne idée. Il en résulte de la confusion code et peut facilement conduire à des bugs où vous oubliez de démarrer sur votre tous votre état sur chaque appel de méthode.
Il serait beaucoup mieux de simplement transmettre ces objets autour de entre les méthodes, et qui permettrait d'éviter tous les problèmes.
Probablement votre ne sont pas correctement à la réinitialisation de la variable d'instance.
Variables d'Instance
En général, nous ne devons pas garder de l'état dans notre bean session sans état. Les objets référencés par les variables d'instance, si ce n'est entaché de nullité après leur utilisation, sont maintenus en vie jusqu'à la fin de la demande et même plus si notre conteneur d'EJB piscines les beans de session afin de les réutiliser. Dans ce dernier cas, nous devons nous assurer que la variable d'instance obtenir correctement réinitialisé lors d'une demande ultérieure. Par conséquent, l'utilisation de variables d'instance peut engendrer les problèmes suivants:
Variables de classe
Comme, par exemple, les variables, les variables de classe ne doit pas être utilisé pour maintenir l'état partagé dans le bean session sans état. Cela ne signifie pas que nous ne devrions pas utiliser le mot-clé static, mais que nous devrions l'utiliser avec prudence (par exemple, définir des constantes immuables, certains statique de la classe factory, etc.)
Parce que c'est très étrange, j'ai effectué un test rapide avec Netbeans et mon Glassfish 2.1.
J'ai modifié le stateless bean à ressembler à cela, comme près de votre exemple possible je pense.
Cela fonctionne comme il se doit. Je ne sais pas ce que l'éditeur que vous utilisez, mais si c'est Netbeans, il peut être intéressant d'exécuter vous-même.
Tout dépend ce que vous entendez par "le niveau de la classe de la variable". Une variable de classe doit avoir le modificateur static. Si
clName
ne le fait pas, chaque instance de votre bean session sans état possède sa propre copie declName
. Votre serveur Java EE probablement créé un groupement de deux ou plusieurs instances de la stateless session bean, et chacun de vos appels àtestNa()
etsayHello()
est envoyée à l'arbitraire d'un exemple.Je suis tombé sur cette question, quand j'ai eu le même problème. Dans mon cas, la méthode privée définit la variable d'instance. Ce que j'ai remarqué, c'est que, parfois, la variable d'instance est déjà défini, évidemment, à partir d'une précédente demande.
Je suppose que cela a du sens. Lorsque le conteneur ré-utilise une instance mise en cache, comment faut-il savoir comment faire pour effacer les variables...
Pour moi, c'est en ligne avec et confirme à la fois de Pascal référence à l'EJB spec ("variables d'instance sont pris en charge") et de Roquettes du Chirurgien de la recommandation ("ne fais pas cela, utiliser des variables locales à la place").
Le problème avec les variables d'Instance dans stateless.
Selon la spécification JEE même EJB stateless exemple, pourrait être partagée avec un autre client. La manette de la règle est de ne pas créer les variables d'instance dans les Apatrides, les Ejb.
Il pourrait être possible que les deux clients accédant à l'application, en même temps, à condition même de l'EJB instance qui permettrait de créer des problèmes car il y a une incohérence des données.
De sorte qu'il n'est pas une bonne idée d'utiliser les variables d'instance dans EJB stateless beans .
J'ai eu le même problème parce que j'ai utilisé global statique de la variable de classe dans ma classe d'ejb et quand j'ai eu simultanées EJB stateless en cours d'exécution, la variable a été remplacée par d'autres instances.
Champs de classe statique sont partagés entre toutes les instances d'une classe particulière, mais seulement au sein d'une seule Machine Virtuelle Java (JVM). Mise à jour d'une classe statique champ implique une intention de partager la valeur du champ parmi toutes les instances de la classe.
Espère aider quelqu'un d'autre 🙂