Beispiel: Stateful Session Bean
Inhalt:
Anlegen der Enterprise Application
Anlegen der GeometricModelBean
Anlegen der GeometricModelStoreBean
Anlegen des WebClient
Testen des WebClient
Ohne Annotations
Beispiel für eine Stateful Session Bean, auf die per Webclient zugegriffen wird.
Hier gibt es das Projekt zum Download (dies ist ein EAR-Export, die
Importanleitung findet man im Stateless-Beispiel): Stateful.ear
Dieses Beispiel kann übrigens parallel zum Stateless-Beispiel auf den Server deployed werden, da die GeometricModelBean
zwar in beiden Beispielen vorkommt, aber mit unterschiedlichen Namen ins JNDI gehängt wird.
Aufbau des Beispieles
a) Stateless Bean-Klasse mit Remote-Interfaces.
b) Stateful Bean-Klasse mit Remote-Interfaces.
c) Webclient: JSP-Seite
Anlegen der Application
Ein "Enterprise Application Project" mit dem Namen "Stateful" erstellen, ohne Default-Module, aber mit der Option "Generate Deployment Descriptors"
Zu erzeugende Module definieren. Dieses Beispiel benötigt ein EJB-Projekt und ein Webprojekt, jeweils mit der Option "Generate Deployment Descriptors".
Im Project Explorer sollte es so aussehen:
Anlegen der StatelessBean
Die Schritte sind identisch mit denen des letzten Beispiels, einschließlich der Geschäftsmethoden
und der Exceptionklasse "InvalidParameterException".
Ein Unterschied ist dass das Package hier "de.fhw.swtvertiefung.knauf.stateful" lautet.
Außerdem legen wir nur ein Remote Interface an, das LocalInterface "GeometricModelLocal" entfällt.
Die Bean-Klasse implementiert entsprechend nur "GeometricModel".
Anlegen der StatefulBean
Die Bean hat den Namen "GeometricModelStoreBean" im Package "de.fhw.swtvertiefung.knauf.stateful".
Die Bean erhält die Annotation "Stateful":
@Stateful()
public class GeometricModelStoreBean
{
Wir deklarieren drei Membervariablen für die Tripel der Kantenlängen:
private Vector<Double> vectorA = null;
private Vector<Double> vectorB = null;
private Vector<Double> vectorC = null;
Außerdem gibt es zwei Business-Methoden "addCalculation" (hinzufügen eines neuen Satzes von Kantenlängen) und
"getAllCalculations" (alle bisherigen Berechnungen in String-Form zurückliefern, für die Zeilenumbrüche wird ein
HTML-Zeilenumbruch in die Rückgabe eingefügt):
public void addCalculation(double a, double b, double c) throws InvalidParameterException
{
if (a <= 0 || b <= 0 || c <= 0)
throw new InvalidParameterException("Seitenlänge <= 0");
this.vectorA.add(new Double(a));
this.vectorB.add(new Double(b));
this.vectorC.add(new Double(c));
}
public String getAllCalculations()
{
String strReturn = "";
for (int intIndex = 0; intIndex < this.vectorA.size(); intIndex++)
{
if (intIndex > 0)
strReturn += "<br>\r\n";
strReturn += "Anfrage " + intIndex + ": " + this.vectorA.get(intIndex) + "/" + this.vectorB.get(intIndex) + "/"
+ this.vectorC.get(intIndex);
}
return strReturn;
}
Eine Besonderheit werden wir hier anwenden: unsere Stateful Session Bean wird nicht unbedingt physisch neu erzeugt
wenn ein neuer Client sie anfordert, sondern es wird eventuell eine "freie" (keinem anderen Client zugeordnete) Instanz
recycled. Deshalb reicht es nicht die Vektoren im Konstruktor zu erzeugen, sondern wir müssen eine Methode implementieren
die der Container bei jedem neuen Binden an einen Client aufruft.
Dieses Binden geschieht über die Annotation "@PostConstruct":
@PostConstruct()
public void postConstruct()
{
this.vectorA = new Vector<Double>();
this.vectorB = new Vector<Double>();
this.vectorC = new Vector<Double>();
}
Jetzt bauen wir uns das Remote Interface:
@Remote()
public interface GeometricModelStore
{
public abstract void addCalculation(double a, double b, double c) throws InvalidParameterException;
public abstract String getAllCalculations();
}
Anlegen des Webclients
Im Project Exlporer einen Rechtsklick auf "StatefulWeb" ->"WebContent" ausführen und im Contextmenü "New" -> "JSP" wählen.
Als Dateiname wird "GeometricModelTest" angegeben.
Nach dem Klick auf "Finish" hat man die JSP-Seite erstellt und kann den Quellcode
der JSP-Datei einfügen.
Nachbearbeitung:
Damit die JSP-Seite die EJB referenzieren kann, muss eine Referenz auf die JAR-Datei zugefügt werden.
Dazu einen Rechtsklick auf den Project-Explorer-Knoten "StatefulWeb" ausführen und "Properties" wählen.
Unter dem Punkt "J2EE Module Dependencies" -> "J2EE Modules" wählt man die Option "Use EJB JARs" und setzt den
Haken beim JAR der EJB-Datei.
Deklaration der EJB-Referenzen:
"StatefulWeb" -> "WebContent" -> "WEB-INF" -> "web.xml" öffnen, im Elelemt "web-app" wird folgendes eingefügt
(auch hier: sinnlose Einträge in das Pflichtelement "<home>"):
<ejb-ref>
<ejb-ref-name>ejb/GeometricModel</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>java.lang.Object</home>
<remote>de.fhw.swtvertiefung.knauf.stateful.GeometricModel</remote>
</ejb-ref>
<ejb-ref>
<ejb-ref-name>ejb/GeometricModelStore</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>java.lang.Object</home>
<remote>de.fhw.swtvertiefung.knauf.stateful.GeometricModelStore</remote>
</ejb-ref>
Die JSP-Seite "GeometricModelTest.jsp" soll als Startseite möglich sein. Auch das stellen
wir über "web.xml" ein:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>GeometricModelTest.jsp</welcome-file>
</welcome-file-list>
Für die EJB-Referenzen müssen wir außerdem in "StatefulWeb\WebContent\WEB-INF" die Datei jboss-web.xml mit diesem Inhalt
anlegen:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web PUBLIC
"-//JBoss//DTD Web Application 4.2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">
<jboss-web>
<context-root>StatelessWeb</context-root>
<!-- Referenz auf "GeometricModelBean" -->
<ejb-ref>
<ejb-ref-name>ejb/GeometricModel</ejb-ref-name>
<jndi-name>Stateful/GeometricModelBean/remote</jndi-name>
</ejb-ref>
<!-- Referenz auf "GeometricModelStoreBean" -->
<ejb-ref>
<ejb-ref-name>ejb/GeometricModelStore</ejb-ref-name>
<jndi-name>Stateful/GeometricModelStoreBean/remote</jndi-name>
</ejb-ref>
</jboss-web>
Testen des Webclients
Der Test erfolgt über diese URL: http://localhost:8080/StatefulWeb
Achtung: Die Stateful Session Bean ist im Session Context der Webanwendung abgelegt. Der Session Context bleibt uns so lange
zugeordnet wie wir den Browser offen haben (Erkennung erfolgt über ein Cookie), das heißt wenn wir eine neue Session und damit eine frische
Stateful Session Bean haben wollen müssen wir alle gerade offenen Instanzen des Browsers schließen.
Ohne Annotations
Jetzt der Weg ohne Annotations, nur mit Deployment-Deskriptoren:
Die Datei "ejb-jar.xml" im EJB-Projekt muss so geändert werden:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
<display-name>StatefulEJB</display-name>
<enterprise-beans>
<session>
<description>
<![CDATA[Stateless Session Bean für einfache geometrische Berechnungen.]]>
</description>
<display-name>GeometricModelBean</display-name>
<ejb-name>GeometricModelBean</ejb-name>
<remote>de.fhw.swtvertiefung.knauf.stateful.GeometricModel</remote>
<ejb-class>de.fhw.swtvertiefung.knauf.stateful.GeometricModelBean</ejb-class>
<session-type>Stateless</session-type>
</session>
<session>
<description>
<![CDATA[Stateful Session Bean für die Speicherung der Berechnungs-Historie.]]>
</description>
<display-name>GeometricModelStoreBean</display-name>
<ejb-name>GeometricModelStoreBean</ejb-name>
<remote>de.fhw.swtvertiefung.knauf.stateful.GeometricModelStore</remote>
<ejb-class>de.fhw.swtvertiefung.knauf.stateful.GeometricModelStoreBean</ejb-class>
<session-type>Stateful</session-type>
<post-construct>
<lifecycle-callback-class>
de.fhw.swtvertiefung.knauf.stateful.GeometricModelStoreBean
</lifecycle-callback-class>
<lifecycle-callback-method>postConstruct</lifecycle-callback-method>
</post-construct>
</session>
</enterprise-beans>
</ejb-jar>
Es gibt zwei Besonderheiten im Vergleich zum Stateless-Beispiel (fett markiert): die Deklaration der GeometricModelStoreBean als "Stateful"
und das Mapping des Lifecycle-Callbacks "PostConstruct" auf die Methode der Bean. Der Rest des Projekts ist absolut identisch mit dem Annotation-igen
Beispiel.
Die modifizierte Version des Projekts gibt es hier: StatefulNoAnnotation.ear.
ACHTUNG: Dieses Projekt kann nicht neben dem obigen Stateful-Beispiel existieren !
Stand 21.10.2007
Historie:
21.10.2007: Erstellt aus Vorjahresbeispiel, angepaßt an WTP 2.0.