2010-02-28 6 views
81

Je parcours le didacticiel Java EE 6 et j'essaie de comprendre la différence entre les beans de session sans état et avec état. Si les beans de session sans état ne conservent pas leur état entre les appels de méthodes, pourquoi mon programme agit-il comme il est?Beans Java Enterprise sans état et avec état

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 me attendais getNumber retourner 0 à chaque fois, mais il retourne 1 et rechargements du servlet dans mon navigateur augmenter plus. Le problème est avec ma compréhension du fonctionnement des beans de session sans état et non avec les bibliothèques ou le serveur d'applications, bien sûr. Est-ce que quelqu'un peut me donner un simple exemple d'un bean session sans état qui se comporte différemment lorsque vous le changez en stateful?

+6

Connexe: http://stackoverflow.com/questions/8887140/jsf-request-scoped-bean-keeps-recreating-new-stateful-session-beans-on-every-req Cette réponse est peut-être plus simple à comprendre. Notez que les servlets sont essentiellement une application étendue (il n'y a qu'une instance de servlet dans toute l'application qui est partagée/réutilisée dans toutes les requêtes/sessions HTTP) – BalusC

+0

hi, Vous commencez par incrémenter, puis vous obtenez la valeur .... donc vous ne pouvez pas attendre la valeur 0 – rzur2004

+0

Je veux juste vous remercier d'avoir posé cette question, cela répond à mon problème pour le moment Je n'aurais pas pu demander mieux –

Répondre

88

La différence importante n'est pas les variables de membre privé, mais l'association de l'état avec un utilisateur particulier (pensez "panier").

La partie stateful du bean session stateful est semblable à la session dans les servlets. Les beans de session avec état permettent à votre application d'avoir cette session même s'il n'y a pas de client Web. Lorsque le serveur d'applications extrait un bean session sans état du pool d'objets, il sait qu'il peut être utilisé pour satisfaire toute requête, car il n'est pas associé à un utilisateur particulier. Un bean session stateful doit être distribué à l'utilisateur qui l'a obtenu en premier lieu, car leurs informations de panier ne doivent être connues que d'eux. Le serveur d'application s'assure que c'est ainsi. Imaginez la popularité de votre application si vous pouviez commencer à magasiner, puis le serveur d'applications vous a donné votre session bean stateful lorsque je suis arrivé! Votre membre de données privé est en effet "é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 c'est fait correctement, chaque utilisateur devrait voir juste leur version du compteur.

+0

Pouvez-vous fournir une réponse explicite dans un commentaire? Pourquoi le bean sans état de cet exemple détient-il toujours la valeur? Parce qu'il n'y a qu'un seul utilisateur – arjacsoh

+2

Le compteur augmentera quel que soit le nombre d'utilisateurs Si user1 entre et incrémente le compteur à 1 et simultanément user2 et l'incrémente, la valeur sera 2. Il devrait en fait montrer que user1 a 1 et user2 a 1 (si c'est ce que vous avez l'intention de faire.) Exemple de panier d'achat comme ci-dessus) – Krishna

16

Stateless et stateful dans ce contexte ne signifie pas tout à fait ce que vous pourriez vous attendre.

L'état avec les EJB fait référence à ce que j'appelle état conversationnel. L'exemple classique est une réservation de vol. Si elle se compose de trois étapes:

  • siège Réserve
  • de carte de crédit de charge
  • Émission de billets

Imaginez chacun d'entre eux est un appel de méthode à un bean de session. Un bean de session avec état peut maintenir ce type de conversation afin qu'il se souvienne de ce qui se passe entre les appels.

Les beans de session sans état n'ont pas cette capacité pour l'état conversationnel.

Les variables globales à l'intérieur d'un bean session (sans état ou stateful) sont entièrement différentes. Les beans session stateful auront un pool de beans créé (car un bean ne peut être utilisé que dans une conversation à la fois) alors que les beans sesion sans état auront souvent une seule instance, ce qui fera fonctionner la variable globale, mais je ne pense pas ceci est nécessairement garanti.

125

beans stateless session (SLSB) sont pas liés à un client et il n'y a aucune garantie pour un client pour obtenir la même instance à chaque appel de méthode (certains conteneurs peuvent créer et détruire les haricots avec chaque session d'appel 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 dépendent pas d'eux entre les appels distants.

En revanche, Stateful Session Beans (SFSB) sont dédiés à un client pour toute leur vie, il n'y a aucun échange ou la mise en commun des cas (il peut être expulsé de la mémoire après passivation d'économiser des ressources, mais c'est une autre histoire) et maintenir l'état conversationnel. Cela signifie que les variables d'instance du bean peuvent conserver les données relatives au client entre les invocations de méthode. Cela permet d'avoir des appels de méthode interdépendants (les changements apportés par une méthode affectent les appels de méthode ultérieurs). Les processus en plusieurs étapes (un processus d'enregistrement, un panier, un processus de réservation ...) sont des cas d'utilisation typiques pour la SFSB.

Encore une chose. Si vous utilisez SFSB, alors vous devez éviter de les injecter dans des classes qui sont multithread dans la nature, tels 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'objet HttpSession pour une activité future. Quelque chose comme ça:

try { 
    InitialContext ctx = new InitialContext(); 
    myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean"); 
    session.setAttribute("my_stateful", myStateful); 
} catch (Exception e) { 
    // exception handling 
} 
+0

Merci pour l'éclaircissement. Lorsque j'utilise un programme de ligne de commande autonome pour le client, il est évident de voir la différence. –

+0

Merci pour cette précision - c'était exactement l'information que je cherchais. –

+0

merci pour vos commentaires, ils sont plus éclairants. D'abord, donnez la définition abstraite, puis spécifiez quelques cas d'utilisation pour chaque situation, puis signalez quelques pièges. Great +1 – arthur

4

Cette chose arrive parce que le conteneur n'a qu'une seule instance de bean dans le pool qui est réutilisé 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.

1

Il a de bonnes réponses. Je voudrais ajouter une petite réponse. Stateless Bean ne doit pas être utilisé pour stocker des données client. Il devrait être utilisé pour «modéliser des actions ou des processus qui peuvent être réalisés en une seule fois».

3

Les principales différences entre les deux principaux types de haricots de session sont:

haricots Apatrides

  1. Stateless Session Beans sont ceux qui n'ont pas état de conversation avec le client qui a appelé ses méthodes. Pour cette raison, ils peuvent créer un pool d'objets qui peuvent être utilisés pour interagir avec plusieurs clients.
  2. Les haricots sans état de performance sont meilleurs car ils n'ont pas d'états par client.
  3. Ils peuvent gérer plusieurs demandes provenant de plusieurs clients en parallèle.

haricots Stateful

  1. haricots session stateful peuvent maintenir l'état de conversation avec plusieurs clients à la fois et la tâche n'est pas partagée entre les clients.
  2. Une fois la session terminée, l'état n'est pas conservé.
  3. Le conteneur peut sérialiser et stocker l'état en tant qu'état périmé pour une utilisation future. Ceci est fait pour économiser les ressources du serveur d'application et pour supporter les échecs du bean.