EJB-Tutorial für JEE6 - Java Enterprise Edition 6 (JSR-318)

28.09.2012

EJB-Tutorial für JEE6 - Java Enterprise Edition 6

In diesem Tutorial werden die drei Session-Bean-Typen Stateless Session Bean, Stateful Session Bean und Singleton Bean vorgestellt. Für jeden Bean-Type wird eine sehr einfache Beispiel-Implementierung erstellt, auf die über eine JSF-Seite zugegriffen werden kann.

In dem Beispiel geht es nicht darum alles Features und Möglichkeiten von EJBs zu beschreiben. Es soll vielmehr vermittelt werden, wo die Unterschiede zwischen den drei Bean-Typen sind und wie einfach es ist, sie über JSF-Seiten anzusprechen.

Am Ende des Artikels findet man eine Liste mit weiterführenden Tutorials.

Stateless Session Bean

Als erstes erstellen wir ein sehr einfaches Stateless Session Bean. Wie der Name schon sagt, speichert es keine Zustände (Stateless), d.h. der "Client" sendet ein Anfrage an das Bean, welche verarbeitet wird und liefert ggf. eine Antwort.

Anwendungsfall für diesen Bean-Typen sind beispielsweise Abfragen gegen eine Datenbank oder eine Berechnung, die auf dem Server durchgeführt werden soll.

Die Stateless Beans werden in einem Pool gehalten, d.h. sie bleiben ggf. erhalten, wenn sie eine Client-Anfrage verarbeitet haben. Wenn ein anderer Client nun eine zweite Anfrage stellt, kann die "alte" Bean wieder verwendet werden und muss nicht erneut erstellt werden.

In dem Beispiel soll eine Methode int numberOfItems() angeboten werden, die der Einfachheit wegen die Zahl 42 zurückliefert.

Dazu legen wir eine Klasse ItemService an, die genau diese eine Methode besitzt. Wichtig ist die Annotation @Stateless, die angibt, dass es sich um eine Stateless Session Bean handelt. Die Annotation @Named wird benötigt, damit die JSF-Seite die Bean findet.

package org.hameister.warehouse;

import javax.ejb.LocalBean;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.inject.Named;

/**
 *
 * @author Hameister
 */

@Stateless
@Named
public class ItemService {
    public String numberOfItems() {
        return "42";
    }
}

Stateful Session Bean

Als zweites erstellen wir eine Stateful Session Bean. Bei dem Namen sollte klar sein, dass ein Zustand gespeichert wird. D.h., wenn der "Client" eine Anfrage stellt, wird die Bean erstellt und bleibt so lange für den Client erhalten, bis die Session abläuft oder der Client beendet wird.

Als Beispiel für diesen Bean-Type muss oft ein virtueller Einkaufswagen herhalten, der nach und nach mit Waren gefüllt wird. Beispielsweise bei Online-Händlern.

In dem Beispiel soll es zwei Methoden geben. Mit der einen Methode kann die Anzahl von Items erhöht werden und mit der anderen Methode lässt sich die Anzahl der Items abfragen.

Dazu legen wir eine Klasse ItemServiceStateful mit den zwei Methoden an. Wichtig ist die Annotation @Stateful, die angibt, dass es sich um eine Stateful Session Bean handelt. Die Annotation @Named wird benötigt, damit die JSF-Seite die Bean findet. Mit der Annotation @StatefulTimeout legen wir eine Zeitspanne fest, in der die Bean erhalten bleibt. D.h. nach 30 Minuten ohne Zugriff wird die Bean gelöscht. Als Scope wurde hier SessionScoped verwendet, d.h. wenn der Client die Verbindung beendet, dann wird der Zählerstand gelöscht. Würde man @ApplicationScoped verwenden, dann bliebe die Bean solange erhalten, bis der Server heruntergefahren wird. Außerdem wäre der Zählerstand auch über einen anderen Client zugreifbar. Beispielsweise einen zweiter Browser.

package org.hameister.warehouse;

import java.util.concurrent.TimeUnit;
import javax.ejb.Stateful;
import javax.ejb.StatefulTimeout;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

/**
 *
 * @author Hameister
 */
@Stateful
@Named
@StatefulTimeout(unit = TimeUnit.MINUTES, value = 30)
@SessionScoped
//@ApplicationScoped
public class ItemServiceStateful { 
    private Integer numberOfItems = 0;
    
    public void increaseItems() {
        numberOfItems++;
    }
    
    public int numberOfItems() {
        return numberOfItems;
    }

}

Singleton Bean

Als drittes erstellen wir ein Singleton Bean. Der Name sagt schon, dass diese Bean nur einmal innerhalb des Containers des Application-Servers existiert. D.h. jeder Client greift auf die gleiche Bean zu. Für einen Cluster gilt das nicht!

Anwendungsgebiet für diesen Bean-Type ist beispielsweise ein Cache. (Vorsicht mit Caches. Überlegen, ob man sie wirklich braucht. ;-) )

Wie schon beim Stateful Bean soll es zwei Methoden geben, mit denen man den Zählerstand erhöhen und auch abfragen kann.

Dazu legen wir eine Klasse ItemServiceSingleton mit den zwei Methoden an. Wichtig ist die Annotation @Singleton, die angibt, dass es sich um eine Singleton Bean handelt. Die Annotation @Named wird benötigt, damit die JSF-Seite die Bean findet. Sonst ist nichts notwendig.

package org.hameister.warehouse;

import javax.ejb.Singleton;
import javax.inject.Named;

/**
 *
 * @author Hameister
 */
@Singleton
@Named
public class ItemServiceSingleton {
    
    private Integer numberOfItems = 0;
    
    public void increaseItems() {
        numberOfItems++;
    }
    
    public int numberOfItems() {
        return numberOfItems;
    }
}

JSF-Seite zum Ansprechen des Beans

Was jetzt noch fehlt ist eine Art Client, der die Beans ansprechen und testen kann. Dazu verwenden wir eine einfach JSF-Seite.

Die Beans werden der Reihe nach angesprochen. Bei der Stateless Session Bean wird nur der Wert 42 abgefragt und mit dem Element outputText angezeigt. Bei der Stateful Session Bean wird ein Button zum Erhöhen des Zählerstands mit Hilfe des Elements commandButton angezeigt. Beim Klick auf den Button, wird die Methode increaseItems() aufgerufen. Außerdem wir die Anzahl der Items durch den Aufruf numberOfItems abgefragt und mit outputText angezeigt. Für das Singleton Bean wird genau das gleiche getan.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>JEE6 - Session Beans - Tutorial - Example</title>
    </h:head>
    <h:body>
        <h:form>
            <h1>Stateless Session Bean</h1>
            <h:outputText value="Value: #{itemService.numberOfItems()}"/>
   
            <h1>Stateful Session Bean</h1>
            <h:commandButton action="#{itemServiceStateful.increaseItems()}" value="Increase"/>
            <h:outputText value="Number of Items: #{itemServiceStateful.numberOfItems()}"/>
            
            <h1>Singleton Bean</h1>
            <h:commandButton action="#{itemServiceSingleton.increaseItems()}" value="Increase"/>
            <h:outputText value="Number of Items: #{itemServiceSingleton.numberOfItems()}"/>
        </h:form>
    </h:body>
</html>

Auf dem folgenden Screenshot sieht man die Anzeige der Seite in einem Browser.

Create New Project

Interessant ist jetzt das Verhalten, wenn man mehrere Browser öffnet. Beispielsweise einen Safari und einen Firefox. Die 42 wird in allen Browsern angezeigt. Wenn man die Browser nacheinander öffnet, dann wird auch nur eine Bean erstellt. Bei der Stateful Session Bean ist es so, dass für jeden Browser eine eigene Bean erzeugt wurde, d.h. wenn man den Zähler in dem einen Browser erhöht, hat es keinen Einfluss auf den Zählerstand im anderen Browser. Bei dem Singleton ist es so, dass nur eine einzige Bean erstellt wurde und wenn der Wert in dem einen Browser erhört wird, dann erhöht sich auch der Wert in dem anderen Browser. (Es findet kein automatischer Refresh statt.)

Weitere Informationen

Die Enterprise JavaBeans 3.1 gehören zum JSR-318. Hier findet man das PDF mit der Spezifikation dazu.

Weitere Informationen zum Thema EJBs findet man hier: