2010-02-28 10 views
81

Ich gehe durch die Java EE 6-Lernprogramm und ich versuche, den Unterschied zwischen Stateless und Stateful Session-Beans zu verstehen. Wenn statusfreie Session-Beans ihren Status zwischen Methodenaufrufen nicht beibehalten, warum verhält sich mein Programm so wie es ist?Stateless und Stateful Enterprise Java Beans

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++; 
    } 
} 

Der Kunde

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()); 
    } 

} 

ich getNumber erwartete jedes Mal zurück 0, aber es 1 und Neuladen des Servlets in meinem Browser zurückkehrt erhöhen es. Das Problem besteht darin, dass ich weiß, wie zustandslose Session-Beans funktionieren und natürlich nicht mit den Bibliotheken oder dem Anwendungsserver. Kann mir jemand ein einfaches Hallo-Welt-Beispiel für eine Stateless-Session-Bean geben, das sich anders verhält, wenn Sie es in Stateful ändern?

+6

Verwandte: http://stackoverflow.com/questions/8887140/jsf-request-scoped-bean-keeps-recreating-new-stateful-session-beans-on-every-req Diese Antwort ist vielleicht einfacher verstehen. Beachten Sie, dass Servlets grundsätzlich anwendungsspezifisch sind (es gibt nur 1 Servlet-Instanz, die für alle HTTP-Anfragen/Sitzungen verwendet wird). – BalusC

+0

hi, Sie inkrementieren zuerst und erhalten dann den Wert .... Sie können also keinen Wert von 0 erwarten – rzur2004

+0

Ich möchte Ihnen nur dafür danken, dass Sie dies fragen, es adressiert mein Problem im Moment. Ich hätte das besser nicht fragen können –

Antwort

88

Der wichtige Unterschied besteht nicht darin, private Membervariablen zu verwenden, sondern den Status einem bestimmten Benutzer zuzuordnen (denken Sie an "Einkaufswagen").

Das stateful Stück der Stateful Session Bean ist wie die Sitzung in Servlets. Stateful Session-Beans ermöglichen es Ihrer App, diese Sitzung auch dann zu haben, wenn kein Webclient vorhanden ist. Wenn der Anwendungsserver eine statusfreie Session-Bean aus dem Objektpool abruft, weiß er, dass sie zur Erfüllung von ANY-Anfragen verwendet werden kann, da sie keinem bestimmten Benutzer zugeordnet ist.

Eine Stateful Session Bean muss an den Benutzer ausgegeben werden, der es zuerst bekommen hat, weil ihre Einkaufswageninformationen nur ihnen bekannt sein sollten. Der App-Server sorgt dafür, dass dies so ist. Stellen Sie sich vor, wie beliebt Ihre App wäre, wenn Sie einkaufen könnten, und der App-Server hat mir dann Ihre Stateful-Session-Bean gegeben, als ich mitkam!

So ist Ihr privates Datenmitglied zwar "State", aber es ist nicht "Einkaufswagen". Versuchen Sie, Ihr (sehr gutes) Beispiel zu wiederholen, damit die inkrementierte Variable einem bestimmten Benutzer zugeordnet wird. Inkrementieren Sie es, erstellen Sie einen neuen Benutzer, und sehen Sie, ob sie den erhöhten Wert weiterhin anzeigen können. Wenn es richtig gemacht wird, sollte jeder Benutzer nur seine Version des Zählers sehen.

+0

Kannst du in einem Kommentar eine explizite Antwort geben? Warum hält immer die stateless Bohne in diesem Beispiel den Wert und Erhöhen Sie es jedes Mal? Weil es nur einen Benutzer gibt? – arjacsoh

+2

Der Zähler wird unabhängig von der Anzahl der Benutzer erhöht.Wenn also Benutzer1 hereinkommt und den Zähler auf 1 erhöht und gleichzeitig Benutzer2 hereinkommt und es erhöht, ist der Wert 2. Es sollte eigentlich zeigen, dass user1 1 hat und user2 1 hat (wenn das ist, was Sie vorhaben. Warenkorb Beispiel wie oben). – Krishna

16

Stateless und Stateful in diesem Zusammenhang bedeuten nicht ganz, was Sie erwarten könnten.

Die Anfälligkeit mit EJBs bezieht sich auf das, was ich Konversationsstatus. Das klassische Beispiel ist eine Flugbuchung. Wenn es besteht aus drei Schritten:

  • Reserve Sitz
  • Gebühr Kreditkarte
  • Ausgabe Ticket

Stellen Sie sich vor jedem von denen ist ein Methodenaufruf zu einem Session-Bean. Eine Stateful Session-Bean kann diese Art von Konversation so beibehalten, dass es sich erinnert, was zwischen Anrufen passiert.

Statuslose Session-Beans verfügen nicht über diese Kapazität für den Konversationsstatus.

Globale Variablen innerhalb einer Session-Bean (zustandslos oder Stateful) sind etwas ganz anderes. Stateful Session-Beans werden einen Pool von Beans erzeugen (da ein Bean nur in einer Konversation verwendet werden kann), während Stateless Beans oft nur eine Instanz haben, wodurch die globale Variable funktioniert, aber ich denke nicht Dies ist unbedingt gewährleistet.

125

Stateless Session Beans (SLSB) sind nicht an einen Kunden gebunden und es gibt keine Garantie für einen Client die gleiche Instanz mit jedem Methodenaufruf zu erhalten (einige Behälter können Bohnen mit jeder Methodenaufruf Sitzung erstellen und zerstören Dies ist eine implementierungsspezifische Entscheidung, aber Instanzen werden typischerweise zusammengefasst - und Cluster-Umgebungen werden nicht erwähnt. Mit anderen Worten, obwohl zustandslose Beans Instanzvariablen haben können, sind diese Felder nicht für einen Client spezifisch, so dass nicht auf sie zwischen Remoteaufrufen angewiesen ist.

Im Gegensatz dazu Stateful Session Beans (SFSB) sind für ihr ganzes Leben auf einen Client gewidmet, gibt es keinen Austausch oder Zusammenlegung von Instanzen (es aus dem Speicher geräumt werden kann, nach der Passivierung Ressourcen zu sparen, aber das ist eine andere Geschichte) und erhalten Konversationsstatus. Dies bedeutet, dass die Instanzvariablen der Bean Daten zwischen Methodenaufrufen relativ zum Client halten können. Dies ermöglicht interdependente Methodenaufrufe (Änderungen durch eine Methode wirken sich auf nachfolgende Methodenaufrufe aus). Mehrstufige Prozesse (ein Registrierungsprozess, ein Einkaufswagen, ein Buchungsprozess ...) sind typische Anwendungsfälle für SFSB.

Eine weitere Sache. Wenn Sie SFSB verwenden, müssen Sie vermeiden, sie in Klassen, die Multithread-Klassen sind, wie Servlets und JSF-verwaltete Beans, in die Klassen zu injizieren (Sie möchten nicht, dass sie von allen Clients gemeinsam genutzt werden). Wenn Sie SFSB in Ihrer Webanwendung verwenden möchten, müssen Sie eine JNDI-Suche durchführen und die zurückgegebene EJB-Instanz im Objekt HttpSession für zukünftige Aktivitäten speichern. So etwas Ähnliches:

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

Danke für das Aufräumen. Wenn ich ein eigenständiges Befehlszeilenprogramm für den Client verwende, ist es offensichtlich, den Unterschied zu sehen. –

+0

Danke für diese Klarstellung - das war genau die Information, nach der ich gesucht habe. –

+0

danke für Ihre Kommentare, sie sind aufschlussreicher. Zuerst geben Sie die abstrakte Definition an, geben dann einige Anwendungsfälle für jede Situation an und weisen dann auf einige Fallstricke hin. Großartig +1 – arthur

4

Das Ding geschehen, weil der Behälter nur eine Bean-Instanz im Pool hat, die für alle Anrufe wiederverwendet wird. Wenn Sie die Clients parallel ausführen, wird ein anderes Ergebnis angezeigt, da der Container mehr Bean-Instanzen im Pool erstellt.

1

Es hat gute Antworten. Ich möchte eine kleine Antwort hinzufügen. Stateless Bean sollte keine Client-Daten speichern. Es sollte verwendet werden, um "Aktionen oder Prozesse zu modellieren, die auf einmal durchgeführt werden können".

3

Die großen Unterschiede zwischen den beiden Haupttypen von Session Beans sind:

Stateless Beans

  1. Stateless Session Beans sind diejenigen, die keine Gesprächszustand mit dem Kunden haben, die genannt hat seine Methoden. Aus diesem Grund können sie einen Pool von Objekten erstellen, die für die Interaktion mit mehreren Clients verwendet werden können.
  2. Leistungsfähige zustandslose Bohnen sind besser, da sie keine Zustände pro Client haben.
  3. Sie können mehrere Anfragen von mehreren Clients parallel behandeln.

Stateful Beans

  1. Stateful Session Beans kann den Gesprächszustand mit mehreren Clients zu einem Zeitpunkt erhalten und die Aufgabe wird nicht zwischen den Clients gemeinsam genutzt.
  2. Nach Abschluss der Sitzung wird der Status nicht beibehalten.
  3. Der Container kann den Status als veralteten Zustand für zukünftige Verwendung serialisieren und speichern. Dies geschieht, um Ressourcen des Anwendungsservers zu sparen und Bean-Fehler zu unterstützen.