Je suis en train de suivre le didacticiel Java EE 6 et j'essaie de comprendre la différence entre les beans session sans état et avec état. Si les beans session sans état ne conservent pas leur état entre les appels de méthode, pourquoi mon programme agit-il ainsi?
package mybeans;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@LocalBean
@Stateless
public class MyBean {
private int number = 0;
public int getNumber() {
return number;
}
public void increment() {
this.number++;
}
}
Le client
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
import mybeans.MyBean;
import java.io.PrintWriter;
@WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" })
public class ServletClient extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
MyBean mybean;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
mybean.increment();
out.println(mybean.getNumber());
}
}
Je m'attendais à ce que getNumber renvoie 0 à chaque fois, mais il renvoie 1 et les recharges du servlet dans mon navigateur l'augmentent davantage. Le problème vient de ma compréhension du fonctionnement des beans session sans état et non des bibliothèques ou du serveur d'applications, bien sûr. Quelqu'un peut-il me donner un exemple simple de type hello world d'un bean session sans état qui se comporte différemment lorsque vous le changez en stateful?
java
jakarta-ee
ejb
ejb-3.1
stateful-session-bean
Stanley Kelly
la source
la source
Réponses:
La différence importante ne réside pas dans les variables de membre privé, mais dans l'association d'un état à un utilisateur particulier (pensez à «panier»).
Le morceau avec état du bean session avec état est comme la session dans les servlets. Les beans session avec état permettent à votre application de conserver cette session même s'il n'y a pas de client Web. Lorsque le serveur d'application extrait un bean session sans état du pool d'objets, il sait qu'il peut être utilisé pour satisfaire N'IMPORTE QUELLE requête, car il n'est associé à aucun utilisateur particulier.
Un bean session avec état doit être distribué à l'utilisateur qui l'a obtenu en premier lieu, car les informations de son panier ne doivent être connues que de lui. Le serveur d'application garantit qu'il en est ainsi. Imaginez à quel point votre application serait populaire si vous pouviez commencer à magasiner, puis le serveur de l'application m'a donné votre bean session avec état lorsque je suis arrivé!
Donc, votre membre de données privées est bien "état", mais ce n'est pas "panier". Essayez de refaire votre (très bon) exemple pour que la variable incrémentée soit associée à un utilisateur particulier. Incrémentez-le, créez un nouvel utilisateur et voyez s'il peut toujours voir la valeur incrémentée. Si cela est fait correctement, chaque utilisateur ne devrait voir que sa version du compteur.
la source
Stateless Session Beans (SLSB) ne sont pas liés à un client et il n'y a aucune garantie pour un client d'obtenir la même instance avec chaque appel de méthode (certains conteneurs peuvent créer et détruire des beans avec chaque session d'invocation de méthode, il s'agit d'une décision spécifique à l'implémentation , mais les instances sont généralement regroupées - et je ne mentionne pas les environnements en cluster). En d'autres termes, bien que les beans sans état puissent avoir des variables d'instance, ces champs ne sont pas spécifiques à un client, donc ne vous fiez pas à eux entre les appels distants.
En revanche, les Stateful Session Beans (SFSB) sont dédiés à un client pour toute sa vie, il n'y a pas d'échange ou de regroupement d'instances (il peut être expulsé de la mémoire après passivation pour économiser des ressources mais c'est une autre histoire) et maintenir l'état de conversation . Cela signifie que les variables d'instance du bean peuvent conserver des données relatives au client entre les appels de méthode. Et cela permet d'avoir des appels de méthode interdépendants (les modifications apportées par une méthode affectent les appels de méthode suivants). Les processus en plusieurs étapes (un processus d'enregistrement, un panier d'achat, un processus de réservation ...) sont des cas d'utilisation typiques de SFSB.
Encore une chose. Si vous utilisez SFSB, vous devez éviter de les injecter dans des classes de nature multithread, telles que les servlets et les beans gérés JSF (vous ne voulez pas qu'il soit partagé par tous les clients). Si vous souhaitez utiliser SFSB dans votre application Web, vous devez effectuer une recherche JNDI et stocker l'instance EJB renvoyée dans l'
HttpSession
objet pour une activité future. Quelque chose comme ca:la source
Stateless et stateful dans ce contexte ne signifient pas tout à fait ce à quoi vous pourriez vous attendre.
L'état avec les EJB fait référence à ce que j'appelle l'état conversationnel . L'exemple classique est une réservation de vol. S'il se compose de trois étapes:
Imaginez que chacun d'entre eux soit un appel de méthode à un bean session. Un bean session avec état peut maintenir ce type de conversation afin de se souvenir de ce qui se passe entre les appels.
Les beans session sans état n'ont pas une telle capacité pour l'état conversationnel.
Les variables globales à l'intérieur d'un bean session (sans état ou avec état) sont tout autre chose. Les beans session avec état auront un pool de beans créé (puisqu'un bean ne peut être utilisé que dans une conversation à la fois) alors que les beans sesion sans état n'auront souvent qu'une seule instance, ce qui fera fonctionner la variable globale, mais je ne pense pas cela est nécessairement garanti.
la source
Les principales différences entre les deux principaux types de session beans sont:
Haricots apatrides
Stateful Beans
la source
Cela se produit car le conteneur n'a qu'une seule instance de bean dans le pool qui est réutilisée pour tous les appels. Si vous exécutez les clients en parallèle, vous verrez un résultat différent car le conteneur créera plus d'instances de bean dans le pool.
la source
Il a de bonnes réponses. Je voudrais ajouter une petite réponse. Stateless Bean ne doit pas contenir de données client. Il doit être utilisé pour "modéliser des actions ou des processus qui peuvent être réalisés en une seule fois".
la source
Bonne question,
essayez ce code (changez MyBean Stateful / Stateless.):
Servlet_1
Servlet_2
cas: MyBean - @ Stateless
http: // localhost: 8080 / MYServletDemo / ServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
2
http: // localhost: 8080 / MYServletDemo_war_exploded / newServletClient
3
http: // localhost: 8080 / MYServletDemo / ServletClient
4
case: MyBean - @ Stateful
http: // localhost: 8080 / MYServletDemo / ServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
2
http: // localhost: 8080 / MYServletDemo / newServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
3
la source