SeamFramework.orgCommunity Documentation

Web Beans: Java Kontexte und "Dependency"-Einspeisung

Der neue Java Standard für "Dependency"-Einspeisung und kontextuelles Status-Management


Hinweis
I. Verwendung kontextueller Objekte
1. Erste Schritte mit Web Beans
1.1. Ihr erstes Web Bean
1.2. Was ist ein Web Bean?
1.2.1. API-Typen, Binding-Typen und Dependency-Einspeisung
1.2.2. Deployment-Typen
1.2.3. Geltungsbereich
1.2.4. Web Bean Namen und Unified EL
1.2.5. Interzeptor Binding-Typen
1.3. Welche Art von Objekten können Web Beans sein?
1.3.1. Einfache Web Beans
1.3.2. Enterprise Web Beans
1.3.3. Producer-Methoden
1.3.4. JMS-Endpunkte
2. Beispiel einer JSF-Webanwendung
3. Die Web Beans Referenzimplementierung
3.1. Das numberguess-Beispiel
3.2. Das translator-Beispiel
4. Dependency-Einspeisung
4.1. Binding-Annotationen
4.1.1. Binding-Annotationen mit Mitgliedern
4.1.2. Kombinationen von Binding-Annnotationen
4.1.3. Binding-Annotationen und Producer-Methoden
4.1.4. Der standardmäßige Binding-Typ
4.2. Deployment Typen
4.2.1. Aktivierung von Deployment-Typen
4.2.2. Deployment-Typ Präzedenz
4.2.3. Beispiel Deployment-Typen
4.3. Unbefriedigende Abhängigkeiten beheben
4.4. Client-Proxies
4.5. Erhalt eines Web Beans durch programmatsichen "Lookup"
4.6. Lebenszyklus-Callbacks, @Resource, @EJB und @PersistenceContext
4.7. Das InjectionPoint-Objekt
5. Geltungsbereiche und Kontexte
5.1. Typen von Geltungsbereichen
5.2. Eingebaute Geltungsbereiche
5.3. Der Geltungsbereich der Konversation
5.3.1. Konversationsdemarkierung
5.3.2. Konversationsfortpflanzung (Conversation Propagation)
5.3.3. Konversations-Timeout
5.4. Der abhängige Pseudo-Geltungsbereich ("Pseudo-Scope")
5.4.1. Die @New-Annotation
6. Producer-Methoden
6.1. Geltungsbereich einer Producer-Methode
6.2. Einspeisung in Producer-Methoden
6.3. Verwendung von @New mit Producer-Methoden
II. Entwicklung lose gepaarten Codes
7. Interzeptoren
7.1. Interzeptor-Bindings
7.2. Implementierung von Interzeptoren
7.3. Interzeptoren aktivieren
7.4. Interzeptor-Bindings mit Mitgliedern
7.5. Multiple Interzeptor bindende Annotationen
7.6. Vererbung von Interzeptor-Binding-Typen
7.7. Verwendung von @Interceptors
8. Dekoratoren
8.1. "Delegate" Attribute
8.2. Aktivierung von Dekoratoren
9. Ereignisse
9.1. Ereignis-Observer
9.2. Ereignis-Producer
9.3. Dynamische Registrierung von Observern
9.4. Ereignis-Bindings mit Mitgliedern
9.5. Multiple Ereignis-Bindings
9.6. Transaktionale Observer
III. Das meiste aus starkem Tippen machen
10. Stereotypen
10.1. Standardmäßiger Geltungsbereich und Deployment-Typ für ein Stereotyp
10.2. Einschränkung des Geltungsbereichs und Typs mit einem Stereotyp
10.3. Interzeptor-Bindings für Stereotypen
10.4. Namensstandardisierung und Stereotype
10.5. Standard-Stereotypen
11. Specialization (Spezialisierung)
11.1. Verwendung von Spezialisierung
11.2. Vorteile von Spezialisierung
12. Definition von Web Beans unter Verwendung von XML
12.1. Deklaration von Web Bean Klassen
12.2. Deklaration von Web Bean Metadaten
12.3. Deklaration von Web Bean Mitgliedern
12.4. Deklaration von inline Web Beans
12.5. Verwendung eines Schemas
IV. Web Beans und das Java EE-Ökosystem
13. Java EE Integration
13.1. Einspeisung von Java EE Ressourcen in ein Web Bean
13.2. Aufruf eines Web Bean von einem Servlet
13.3. Aufruf eines Web Beans von einem Message-Driven Bean
13.4. JMS Endpunkte
13.5. Packen und Deployment
14. Erweiterung von Web Beans
14.1. Das Manager-Objekt
14.2. Die Bean-Klasse
14.3. Das Context-Interface
15. Die nächsten Schritte
A. Integration der Web Beans RI in andere Umgebungen
A.1. Das Web Beans RI SPI
A.1.1. Web Bean Discovery
A.1.2. EJB Discovery
A.1.3. @EJB, @PersistenceContext und @Resource Auflösung
A.1.4. Transaction Services
A.1.5. Der Applikationskontext
A.1.6. Bootstrap und Shutdown
A.1.7. JNDI
A.1.8. Laden von Ressourcen
A.1.9. Servlet injection
A.2. Der Vertrag mit dem Container

Der Name von JSR-299 wurde vor kurzem von "Web Beans" zu "Java Kontexte und Dependency-Einspeisung" geändert. Dieses Handbuch bezieht sich nach wie vor auf JSR-299 als "Web Beans" und die JSR-299 Referenzimplementierung als "Web Beans RI". Andere Dokumentation wie Blogs, Postings in Foren usw. verwenden möglicherweise bereits die neue Namensgebung, darunter den neuen Namen für die JSR-299 Referenzimplementierung - "Web Beans".

You'll also find that some of the more recent functionality to be specified is missing (such as producer fields, realization, asynchronous events, XML mapping of EE resources).

Die Web Beans (JSR-299) Speziifikation definiert einen Satz von Diensten für die Java EE Umgebung, der die Entwicklung von Anwendungen maßgeblich vereinfacht. Web Beans schichtet ein verbessertes Lebenszyklus- und Interaktionsmodell über bestehende Java-Komponententypen, einschließlich JavaBeans und Enterprise Java Beans. Zur Vervollständigung des traditionellen Java EE Programmiermodells bieten Web Beans Dienste:

Dependency-Einspeisung sowie kontextuelles Lebenszyklus-Management erspart dem Benutzer eines unbekannten API das Stellen und die Beantwortung folgender Fragen:

Ein Web Bean legt nur Typ und Semantik anderer Web Beans fest, von denen es abhängt. Es benötigt keine Informationen zum tatsächlichen Lebenszyklus, konkreter Implementierung, dem Threading-Modell oder anderen Clients eines Web Beans von dem es abhängt. Besser noch - die konkrete Implementierung, der Lebenszyklus und das Threading-Modell eines Web Beans von dem es abhängt können je nach Deployment-Szenario variieren, ohne dass dies Auswirkungen auf irgendeinen Client hätte.

Ereignisse, Interzeptoren und Dekoratoren verbessern die lose Paarung, die diesem Modell innewohnt:

Und das Wichtigste - Web Beans bieten all diese Facilities auf typensichere Weise. Web Beans verwenden nie string-basierte Bezeichner, um zu bestimmen, wie zusammenarbeitende Objekte zusammenpassen. Und XML wird - obwohl es nach wie vor eine Option bleibt - wird selten verwendet. Stattdessen verwenden Web Beans die bereits im Java-Objektmodell verfügbaren Typinformationen gemeinsam mit einem neuen Muster namens Binding-Annotationen, um Web Beans, deren Abhängigkeiten, deren Interzeptoren und Dekoratoren sowie deren Ereignis-Consumer zu verbinden.

Die Web Beans Dienste sind allgemein und wenden folgende Komponententypen an, die in der Java EE Umgebung existieren:

Web Beans bieten sogar die nötigen Integrationspunkte, so dass andere Arten von Komponenten, die durch zukünftige Java EE Spezifikationen oder nicht standardmäßige Frameworks definiert werden, sauber mit Web Beans integriert werden sowie die Web Beans Dienste nutzen und mit anderen Arten von Web Beans interagieren können.

Web Beans wurden durch eine Reihe bestehender Java Frameworks beeinflusst, darunter Seam, Guice und Spring. Jedoch besitzen Web Beans ihre eigenen Eigenschaften: Typesicherer als Seam, mehr stateful und weniger XML-zentrisch als Spring, mehr Web- und Enterprise-anwendungsfähig als Guice.

Und das Wichtigste - bei Web Beans handelt es sich um einen JCP-Standard, der sich sauber mit Java EE und mit jeder anderen Java SE Umgebung integrieren lässt, bei der einbettbares EJB Lite verfügbar ist.

Inhaltsverzeichnis

1. Erste Schritte mit Web Beans
1.1. Ihr erstes Web Bean
1.2. Was ist ein Web Bean?
1.2.1. API-Typen, Binding-Typen und Dependency-Einspeisung
1.2.2. Deployment-Typen
1.2.3. Geltungsbereich
1.2.4. Web Bean Namen und Unified EL
1.2.5. Interzeptor Binding-Typen
1.3. Welche Art von Objekten können Web Beans sein?
1.3.1. Einfache Web Beans
1.3.2. Enterprise Web Beans
1.3.3. Producer-Methoden
1.3.4. JMS-Endpunkte
2. Beispiel einer JSF-Webanwendung
3. Die Web Beans Referenzimplementierung
3.1. Das numberguess-Beispiel
3.2. Das translator-Beispiel
4. Dependency-Einspeisung
4.1. Binding-Annotationen
4.1.1. Binding-Annotationen mit Mitgliedern
4.1.2. Kombinationen von Binding-Annnotationen
4.1.3. Binding-Annotationen und Producer-Methoden
4.1.4. Der standardmäßige Binding-Typ
4.2. Deployment Typen
4.2.1. Aktivierung von Deployment-Typen
4.2.2. Deployment-Typ Präzedenz
4.2.3. Beispiel Deployment-Typen
4.3. Unbefriedigende Abhängigkeiten beheben
4.4. Client-Proxies
4.5. Erhalt eines Web Beans durch programmatsichen "Lookup"
4.6. Lebenszyklus-Callbacks, @Resource, @EJB und @PersistenceContext
4.7. Das InjectionPoint-Objekt
5. Geltungsbereiche und Kontexte
5.1. Typen von Geltungsbereichen
5.2. Eingebaute Geltungsbereiche
5.3. Der Geltungsbereich der Konversation
5.3.1. Konversationsdemarkierung
5.3.2. Konversationsfortpflanzung (Conversation Propagation)
5.3.3. Konversations-Timeout
5.4. Der abhängige Pseudo-Geltungsbereich ("Pseudo-Scope")
5.4.1. Die @New-Annotation
6. Producer-Methoden
6.1. Geltungsbereich einer Producer-Methode
6.2. Einspeisung in Producer-Methoden
6.3. Verwendung von @New mit Producer-Methoden

Können Sie es jetzt kaum erwarten Ihr erstes Web Bean zu schreiben? Oder sind Sie etwas skeptisch und fragen sich, welche Hürden Ihnen bei der Web Beans Spezifikation bevorstehen? Die gute Nachricht ist, dass Sie wahrscheinlich schon hunderte, wenn nicht tausende von Web Beans geschrieben haben. Vielleicht erinnern Sie sich nicht einmal an das erste Web Bean, das Sie je geschrieben haben.

Mit bestimmten, ganz besonderen Ausnahmen ist jede Java-Klasse mit einem Konstruktor, die keine Parameter akzeptiert ein Web Bean. Das beinhaltet jedes JavaBean. Desweiteren ist jedes EJB 3-artige Session Bean ein Web Bean. Sicher, die von Ihnen täglich geschriebenen JavaBeans und EJBs konnten die neuen, in der Web Beans Spezifikation definierten Dienste nicht nutzen, aber Sie werden diese allesamt benutzen können können, das Web Beans — diese in andere Web Beans einspeisen, diese via der Web Beans XML-Konfigurationseinrichtung konfigurieren und diesen sogar Interzeptoren und Dekoratoren hinzufügen, ohne den bestehenden Code anzurühren.

Nehmen wir an, Sie besitzen zwei bestehende Java Klassen, die bis dato in verschiedenen Anwendungen verwendet wurden. Die erste Klasse parst einen String in eine Liste von Sätzen:

public class SentenceParser {

    public List<String
> parse(String text) { ... }
}

Bei der zweiten bestehenden Klasse handelt es sich um das Front-End eines "stateless Session Beans" für ein externes System, das in der Lage ist Sätze von einer Sprache in eine andere zu übersetzen:

@Stateless

public class SentenceTranslator implements Translator {
    public String translate(String sentence) { ... }
}

Wo Translator das lokale Interface ist:

@Local

public interface Translator {
    public String translate(String sentence);
}

Leider besitzen wir keine bereits bestehende Klasse die ganze Textdokumente übersetzt. Schreiben wir also ein Web Bean, das diesen Job übernimmt:

public class TextTranslator {

    
    private SentenceParser sentenceParser;
    private Translator sentenceTranslator;
    
    @Initializer
    TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
        this.sentenceParser = sentenceParser;
        this.sentenceTranslator = sentenceTranslator;
    }
    
    public String translate(String text) {
        StringBuilder sb = new StringBuilder();
        for (String sentence: sentenceParser.parse(text)) {
            sb.append(sentenceTranslator.translate(sentence));
        }
        return sb.toString();
    }
    
}

Wir erhalten eine Instanz von TextTranslator durch dessen Einspeisung in ein Web Bean, Servlet oder EJB:

@Initializer

public setTextTranslator(TextTranslator textTranslator) {
    this.textTranslator = textTranslator;
}

Alternativ erhalten wir eine Instanz durch direkten Aufruf einer Methode des Web Bean Managers:

TextTranslator tt = manager.getInstanceByType(TextTranslator.class);

Aber warten Sie: TextTranslator besitzt keinen Konstruktor ohne Parameter! Handelt es sich noch um ein Web Bean? Nun, eine Klasse, die keinen Konstruktor ohne Parameter besitzt, kann nach wie vor Web Bean sein, falls es einen mit @Initializer annotierten Konstruktor besitzt.

Wie Sie wahrscheinlich bereits erraten haben, hat die @Initializer-Annotation etwas mit Dependency-Einspeisung zu tun! @Initializer kann am Konstruktor oder der Methode eines Web Beans angewendet werden und teilt dem Web Bean Manager mit, diesen Konstruktor oder diese Methode bei Instantiierung des Web Beans aufzurufen. Der Web Bean Manager speist andere Web Beans in die Parameter des Konstruktors oder der Methode ein.

Zum Zeitpunkt der Systeminitialisierung muss der Web Bean Manager validieren, dass genau ein Web Bean existiert, das jedem Einspeisungspunkt gerecht wird. Für unser Beispiel bedeutet das, wenn keine Implementierung von Translator verfügbar ist — wenn der SentenceTranslator EJB nicht deployt wurde — dass der Web Bean Manager eine UnsatisfiedDependencyException melden würde. Wäre mehr als eine Implementierung von Translator verfügbar, so würde der Web Bean Manager eine AmbiguousDependencyException melden.

Was also genau ist ein Web Bean?

Bei einem Web Bean handelt es sich um eine Anwendungsklasse, die Business Logik enthält. Ein Web Bean kann direkt von Java Code oder via Unified EL aufgerufen werden. Ein Web Bean kann auf transaktionale Ressourcen zugreifen. Abhängigkeiten zwischen Web Beans werden automatisch durch den Web Bean Manager verwaltet. Die meisten Web Beans sind stateful und kontextbezogen. Der Lebenszyklus eines Web Beans wird immer durch den Web Bean Manager verwaltet.

Erinnern wir uns. Was genau bedeutet es, "kontextuell" zu sein? Da Web Beans "stateful" sein können, ist es relevant welche Bean-Instanz ich besitze. Anders als ein Komponentenmodell, das "stateless" ist (etwas "stateless" Session Beans) oder ein Singleton Komponentenmodell (wie Servlets oder Singleton Beans), sehen verschiedene Clients eines Web Beans das Web Bean in unterschiedlichen Stati. Der Client-sichtbare Status ist abhängig davon, auf welche Instanz des Web Beans der Client verweist (eine Referenz besitzt).

Wie beim "stateless" oder "singleton" Modell anders jedoch als bei "stateful" Session Beans, steuert der Client den Lebenszyklus der Instanz nicht durch expliziertes Erstellen und Löschen. Stattdessen bestimmt der Geltungsbereich des Web Beans:

Für einen bestimmten Thread in einer Web Beans Anwendung kann ein aktiver Kontext mit dem Geltungsbereich des Web Beans assoziiert sein. Dieser Kontext kann eindeutig für den Thread sein (etwa wenn für die Web Bean Anfrage ein Geltungsbereich gilt) oder aber kann mit anderen Threads (etwa wenn für die Web Bean ein Session-Geltungsbereich gilt) oder gar allen Threads (falls ein Anwendungs-Geltungsbereich gilt) geteilt werden.

Clients (etwa andere Web Beans), die in demselben Kontext ausführen sehen dieselbe Instanz des Web Beans. Clients in einem anderen Kontext aber sehen eine andere Instanz.

Ein großer Vorteil des kontextuellen Modells ist es, dass es uns gestattet, stateful Web Beans wie Dienste zu behandeln! Der Client muss sich keine Gedanken um das Management des Lebenszyklus des verwendeten Web Beans machen und muss nicht einmal wissen was der Lebenszyklus ist. Web Beans interagieren durch Weitergabe von Nachrichten und die Web Bean Implementierungen definieren den Lebenszyklus ihres eigenen Status. Die Web Beans sind lose gepaart, weil:

Wir können ein Web Bean durch ein anderes Web Bean ersetzen, das dasselbe API und einen anderen Lebenszyklus (einen anderen Geltungsbereich) besitzt, ohne dass die übrige Web Bean Implementierung hiervon betroffen ist. Genau genommen definieren Web Beans eine raffinierte Einrichtung zur Außerkraftsetzung von Web Bean Implementierungen zum Zeitpunkt des Deployment wie wir in Abschnitt 4.2, „Deployment Typen“ noch sehen werden.

Beachten Sie, dass es sich nicht bei allen Clients eines Web Beans um Web Beans handelt. Andere Objekte wie Servlets oder Message-Driven Beans — die ihrem Wesen nach nicht einspeisbar sind, kontextuelle Objekte — können durch Einspeisung ebenfalls Verweise auf ein Web Beans erhalten.

Formeller gilt, gemäß der Spezifikation:

Ein Web Bean besteht aus:

  • Einem (nicht leeren) Satz von API-Typen

  • Einem (nicht leeren) Satz von bindenden Annotationstypen

  • Einem Geltungsbereich

  • Einem Deployment-Typ

  • Optional einem Web Bean Namen

  • Ein Satz Interzeptor Binding-Typen

  • Einer Web Bean Implementierung

Sehen wir uns jetzt genauer an, was diese Begriffe für einen Entwickler von Web Beans bedeuten.

Web Beans erhalten Verweise auf andere Web Beans in der Regel via "Dependency"-Einspeisung. Jedes eingespeiste Attribut legt einen "Vertrag" fest, der vom einzuspeisenden Web Bean erfüllt sein muss. Der Vertrag lautet:

Bei einem API handelt es sich um eine benutzerdefinierte Klasse oder Interface. (Falls es sich bei dem Web Bean um ein EJB Session Bean handelt, so ist der API-Typ das @Local-Interface oder Bean-Klasse lokale Ansicht). Ein Binding-Typ repräsentiert Client-sichtbare Semantik, die von einigen Implementierungen des API erfüllt wird, von anderen wiederum nicht.

Binding-Typen werden durch benutzerdefinierte Annotationen repräsentiert, die ihrerseits mit @BindingType annotiert sind. Zum Beispiel besitzt der folgende Einspeisungspunkt den API-Typ PaymentProcessor und Binding-Typ @CreditCard:

@CreditCard PaymentProcessor paymentProcessor

Wird an einem Einspeisungspunkt kein Binding-Typ explizit festgelegt, so wird vom standardmäßigen Binding-Typ @Current ausgegangen.

Für jeden Einspeisungspunkt sucht der Web Bean Manager nach einem Web Bean, das den Vertrag erfüllt (das API implementiert und alle Binding-Typen besitzt) und speist dieses Web Bean ein.

Das folgende Web Bean besitzt den Binding-Typ @CreditCard und implementiert den API-Typ PaymentProcessor. Es könnte daher am Beispiel-Einspeisungspunkt eingespeist werden:

@CreditCard

public class CreditCardPaymentProcessor 
    implements PaymentProcessor { ... }

Falls ein Web Bean nicht explizit einen Satz von Binding-Typen festlegt, so besitzt es genau einen Binding-Typ: den standardmäßigen Binding-Typ @Current.

Web Beans definiert einen fortgeschrittenen aber intuitiven Auflösungsalgorithmus, der dem Container dabei hilft zu entscheiden was geschehen soll, wenn mehr als ein Web Bean einen bestimmten Vertrag erfüllt. Wir gehen in Kapitel 4, Dependency-Einspeisung näher darauf ein.

Wir haben bereits gesehen, dass JavaBeans, EJBs und einige andere Java-Klassen Web Beans sein können. Aber um was für Objekte genau handelt es sich bei Web Beans?

Die Spezifikation besagt, dass alle EJB 3-style Session und Singleton Beans Enterprise Web Beans sind. Message-driven Beans sind keine Web Beans — da sie nicht zur Einspeisung in andere Objekte vorgesehen sind — aber sie können den größten Teil der Funktionalität von Web Beans nutzen, darunter auch "Dependency"-Einspeisung und Interzeptoren.

Jedes lokale Interface eines Enterprise Web Beans und jedes seiner Super-Interfaces, das keinen Platzhaltertyp-Parameter oder eine Typenvariable besitzt, ist ein API-Typ des Enterprise Web Beans. Falls das EJB-Bean eine lokale Ansicht der Bean-Klasse besitzt, so handelt es sich auch bei der Bean-Klasse und jede von deren Super-Klassen um einen API-Typ.

Stateful Session Beans sollten eine Entfernungsmethode ("remove method") ohne Parameter oder eine Entfernungsmethode mit der Annotation @Destructor deklarieren. Der Web Bean Manager ruft diese Methode auf, um die Instanz des stateful Session Beans am Ende von deren Lebenszyklus zu löschen. Diese Methode nennt sich Destructor-Methode des Enterprise Web Beans.

@Stateful @SessionScoped

public class ShoppingCart {
    ...
    
    @Remove
    public void destroy() {}
}

Sollten wir also ein Enterprise Web Bean statt eines einfachen Web Beans verwenden? Nun, wenn wir ausgefeilte, durch EJB bereitgestellte Enterprise-Dienste benötigen, wie etwa:

so sollten wir ein Enterprise Web Bean verwenden. Wenn wir nichts von alledem brauchen, so reicht ein einfaches Web Bean vollkommen aus.

Viele Web Beans (einschließlich session- oder anwendungsbegrenzte Web Beans) sind für nebenläufigen Zugriff verfügbar. Daher ist das durch EJB 3.1 bereitgestellte Nebenläufigkeits-Management besonders nützlich. Die meisten session- oder anwendungsbegrenzten Web Beans sollten EJBs sein.

Web Beans, die Verweise auf schwergewichtige Ressourcen oder eine Menge internen Status besitzen, haben Vorteile durch den fortgeschrittenen, Container-gemanagten, durch das EJB @Stateless/@Stateful/@Singleton-Modell definierten Lebenszyklus und dessen Support von Passivation und Instanz-Pooling.

Schließlich ist es offenkundig, wenn Transaktions-Management auf Methodenebene, Sicherheit auf Methodenebene, Timer, Remote-Methoden oder asynchrone Methoden benötigt werden.

Es ist in der Regel leicht, mit einem einfachen Web Bean zu beginnen und es dann zu einem EJB zu machen, indem man eine Annotation: @Stateless, @Stateful oder @Singleton hinzufügt.

Illustrieren wir diese Ideen an einem vollständigen Beispiel. Wir werden einen Benutzer Login/Logout für eine JSF verwendende Anwendung implementieren. Zunächst definieren wir ein Web Bean das den während des Logins eingegebenen Benutzernamen und das Passwort verwahrt:

@Named @RequestScoped

public class Credentials {
        
    private String username;
    private String password;
    
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    
}

Dieses Web Bean ist an den Login-Prompt in folgendem JSF-Formular gebunden:

<h:form>

    <h:panelGrid columns="2" rendered="#{!login.loggedIn}">
        <h:outputLabel for="username"
>Username:</h:outputLabel>
        <h:inputText id="username" value="#{credentials.username}"/>
        <h:outputLabel for="password"
>Password:</h:outputLabel>
        <h:inputText id="password" value="#{credentials.password}"/>
    </h:panelGrid>
    <h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
    <h:commandButton value="Logout" acion="#{login.logout}" rendered="#{login.loggedIn}"/>
</h:form
>

Die eigentliche Arbeit wird durch ein Session-begrenztes Web Bean übernommen, dass Informationen zum aktuell eingeloggten Benutzer verwahrt und anderen Web Beans die User-Entity offenlegt:

@SessionScoped @Named

public class Login {
    @Current Credentials credentials;
    @PersistenceContext EntityManager userDatabase;
    private User user;
    
    public void login() {
            
        List<User
> results = userDatabase.createQuery(
           "select u from User u where u.username=:username and u.password=:password")
           .setParameter("username", credentials.getUsername())
           .setParameter("password", credentials.getPassword())
           .getResultList();
        
        if ( !results.isEmpty() ) {
           user = results.get(0);
        }
        
    }
    
    public void logout() {
        user = null;
    }
    
    public boolean isLoggedIn() {
       return user!=null;
    }
    
    @Produces @LoggedIn User getCurrentUser() {
        return user;
    }
}

Natürlich handelt es sich bei @LoggedIn um eine "Binding"-Annotation:

@Retention(RUNTIME)

@Target({TYPE, METHOD, FIELD})
@BindingType
public @interface LoggedIn {}

Jetzt kann jedes andere Web Bean den aktuellen Benutzer auf leichte Weise einspeisen:

public class DocumentEditor {


    @Current Document document;
    @LoggedIn User currentUser;
    @PersistenceContext EntityManager docDatabase;
    
    public void save() {
        document.setCreatedBy(currentUser);
        docDatabase.persist(document);
    }
    
}

Wir hoffen, dass Ihnen dieses Beispiel einen Vorgeschmack auf das Web Bean Programmiermodell gegeben hat. Im nächsten Kapitel sehen wir uns die Web Beans Dependency-Einspeisung näher an.

Die Web Beans Referenzimplementierung wird unter das Seam Projekt entwickelt. Sie können die aktuellste Entwickler-Release von Web Beans von der Downloads Seite herunterladen.

Die Web Beans RI kommt mit zwei deploybaren Beispielanwendungen: webbeans-numberguess, ein war-Beispiel, das nur einfache Beans enthält und webbeans-translator, ein ear-Beispiel, dasEnterprise Beans enthält. Um Beispiele auszuführen benötigen Sie folgendes:

  • die aktuellste Release der Web Beans RI,

  • JBoss AS 5.0.0.GA und

  • Ant 1.7.0.

Currently, the Web Beans RI only runs on JBoss Application Server 5. You'll need to download JBoss AS 5.0.1.GA from jboss.org, and unzip it. For example:

$ cd /Applications
$ unzip ~/jboss-5.0.1.GA.zip

Anschließend laden Sie die Web Beans RI unter seamframework.org herunter und entzippen diese. Zum Beispiel

$ cd ~/
$ unzip ~/webbeans-$VERSION.zip

Als nächstes müssen wir Web Beans mitteilen, wo JBoss sich befindet. Editieren Sie jboss-as/build.properties und setzen Sie die jboss.home-Property. Zum Beispiel:

jboss.home=/Applications/jboss-5.0.1.GA

Anmerkung

A new deployer, webbeans.deployer is added to JBoss AS. This adds supports for Web Bean archives to JBoss AS, and allows the Web Beans RI to query the EJB3 container and discover which EJBs are installed in your application.

Web Beans is bundled with JBoss AS 5.1 and above.

To install Web Beans, you'll need Ant 1.7.0 installed, and the ANT_HOME environment variable set. For example:

$ unzip apache-ant-1.7.0.zip
$ export ANT_HOME=~/apache-ant-1.7.0

Then, you can install the update. The update script will use Maven to download Web Beans automatically.

$ cd webbeans-$VERSION/jboss-as
$ ant update

Jetzt können Sie Ihr erstes Beispiel deployen!

Tipp

Die Build-Skripte für die Beispiele bieten zahlreiche Ziele, diese sind:

  • ant restart - Deployment des Beispiels in ausgeklapptem Format

  • ant explode - Aktualisierung eines ausgeklappten Beispiels ohne Neustart des Deployments

  • ant deploy - Deployment des Beispiels in komprimiertem jar-Format

  • ant undeploy - das Beispiel vom Server entfernen

  • ant clean - Das Beispiel bereinigen

Um das numberguess Beispiel zu deployen:

$ cd examples/numberguess
ant deploy

JBoss AS starten:

$ /Application/jboss-5.0.0.GA/bin/run.sh

Tipp

Falls Sie Windows verwenden, verwenden Sie das run.bat-Skript.

Deployen Sie die Anwendung und genießen Sie stundenlangen Spaß unter http://localhost:8080/webbeans-numberguess!

Die Web Beans RI enthält ein zweites einfaches Beispiel, das Ihren Text ins Lateinische übersetzt. Beim numberguess Beispiel handelt es sich um ein war-Beispiel und es verwendet nur einfache Beans; das translator-Beispiel ist ein ear-Beispiel, das in einem EJB-Modul verpackte Enterprise Beans enthält . Um dies auszuprobieren:

$ cd examples/translator
ant deploy

Warten Sie, bis die Anwendung deployt ist und besuchen Sie http://localhost:8080/webbeans-translator!

In der numberguess-Anwendung haben Sie 10 Versuche, eine Zahl zwischen 1 und 100 zu erraten. Nach jedem Versuch wird Ihnen mitgeteilt, ob Sie zu hoch oder zu niedrig liegen.

Das numberguess-Beispiel besteht aus einer Reihe von Web Beans, Konfigurationsdateien und Facelet JSF-Seiten, die als eine war verpackt sind. Fangen wir mit den Konfigurationsdateien an.

Alle Konfigurationsdateien für dieses Beispiel befinden sich in WEB-INF/, das in WebContent im Quell-Baum gespeichert ist. Zunächst haben wir faces-config.xml, in dem wir JSF anweisen, Facelets zu verwenden:


<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2"
              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/web-facesconfig_1_2.xsd">
    
    <application>
        <view-handler
>com.sun.facelets.FaceletViewHandler</view-handler>
    </application>

</faces-config
>

Es existiert eine leere web-beans.xml-Datei, die diese Anwendung als Web Beans Applikation kennzeichnet.

Und schließlich gibt es noch web.xml:

Let's take a look at the Facelet view:

<!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:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:s="http://jboss.com/products/seam/taglib">

  <ui:composit(1)ion template="template.xhtml">
    <ui:define name="content">
       <h1
>Guess a number...</h1>
       <h:form(2) id="NumberGuessMain">
          <div style="color: red">
             <h:messages id="messages" globalOnly="false"/>
             <h:outputText id="Higher" value="Higher!" rendered="#{game.number gt game.guess and game.guess ne 0}"/>
             <h:outputText id="Lower" value="Lower!" rendered="#{game.number lt game.guess and game.guess ne 0}"/>
          </div>
   
          <div(3)>
             I'm thinking of a number between #{game.smallest} and #{game.biggest}.
             You have #{game.remainingGuesses} guesses.
          </div>
     
          <div>
             Y(4)our guess: 
             <h:inputText id="inputGuess" 
                          value="#{game.guess}" 
                          required="true" 
                          size="3" 
              (5)            disabled="#{game.number eq game.guess}">
                <f:validateLongRange maximum="#{game.biggest}" 
                                     minimum="#{game.smallest}"/>
             <(6)/h:inputText>
            <h:commandButton id="GuessButton"  
                             value="Guess" 
                             action="#{game.check}" 
                             disabled="#{game.number eq game.guess}"/>
          </div>
          <div>
            <h:commandButton id="RestartButton" value="Reset" action="#{game.reset}" immediate="true" />
          </div>
       </h:form>
    </ui:define>
  </ui:composition>
</html
>
1

Facelets is a templating language for JSF, here we are wrapping our page in a template which defines the header.

2

There are a number of messages which can be sent to the user, "Higher!", "Lower!" and "Correct!"

3

As the user guesses, the range of numbers they can guess gets smaller - this sentance changes to make sure they know what range to guess in.

4

This input field is bound to a Web Bean, using the value expression.

5

A range validator is used to make sure the user doesn't accidentally input a number outside of the range in which they can guess - if the validator wasn't here, the user might use up a guess on an out of range number.

6

And, of course, there must be a way for the user to send their guess to the server. Here we bind to an action method on the Web Bean.

Das Beispiel besteht aus 4 Klassen, wobei die ersten beiden Binding-Typen sind. Zunächst gibt es den @Random Binding-Typ, der zur Einspeisung einer zufälligen Zahl dient:

@Target( { TYPE, METHOD, PARAMETER, FIELD })

@Retention(RUNTIME)
@Documented
@BindingType
public @interface Random {}

Es gibt außerdem den @MaxNumber Binding-Typ, der zur Einspeisung der maximalen Zahl, die eingespeist werden kann, verwendet wird:

@Target( { TYPE, METHOD, PARAMETER, FIELD })

@Retention(RUNTIME)
@Documented
@BindingType
public @interface MaxNumber {}

Die Generator-Klasse ist verantwortlich für die Erstellung der zufälligen Zahl via einer Producer-Methode. Sie legt auch die mögliche Maximalzahl via einer maximum Producer-Methode offen:

@ApplicationScoped

public class Generator {
   
   private java.util.Random random = new java.util.Random( System.currentTimeMillis() );
   
   private int maxNumber = 100;
   
   java.util.Random getRandom()
   {
      return random;
   }
   
   @Produces @Random int next() { 
      return getRandom().nextInt(maxNumber); 
   }
   
   @Produces @MaxNumber int getMaxNumber()
   {
      return maxNumber;
   }
}

Sie werden feststellen, dass der Generator anwendungsbegrenzt ist; daher erhalten wir nicht jedes Mal ein anderes Zufallsergebnis.

Das letzte Web Bean in der Anwendung ist das sessionbegrenzte Game.

Sie werden bemerken, dass wir die @Named-Annotation verwendet haben, damit wir das Bean durch EL in der JSF-Seite verwenden können. Zu guter Letzt haben wir Konstruktor-Einspeisung zur Initialisierung des Spiels mit Zufallszahl verwendet. Und natürlich müssen wir dem Spieler mitteilen, wenn er gewonnen hat, daher bieten wir Feedback mittels einer FacesMessage.

package org.jboss.webbeans.examples.numberguess;



import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.webbeans.AnnotationLiteral;
import javax.webbeans.Current;
import javax.webbeans.Initializer;
import javax.webbeans.Named;
import javax.webbeans.SessionScoped;
import javax.webbeans.manager.Manager;
@Named
@SessionScoped
public class Game
{
   private int number;
   
   private int guess;
   private int smallest;
   private int biggest;
   private int remainingGuesses;
   
   @Current Manager manager;
   
   public Game()
   {
   }
   
   @Initializer
   Game(@MaxNumber int maxNumber)
   {      
      this.biggest = maxNumber;
   }
   public int getNumber()
   {
      return number;
   }
   
   public int getGuess()
   {
      return guess;
   }
   
   public void setGuess(int guess)
   {
      this.guess = guess;
   }
   
   public int getSmallest()
   {
      return smallest;
   }
   
   public int getBiggest()
   {
      return biggest;
   }
   
   public int getRemainingGuesses()
   {
      return remainingGuesses;
   }
   
   public String check()
   {
      if (guess
>number)
      {
         biggest = guess - 1;
      }
      if (guess<number)
      {
         smallest = guess + 1;
      }
      if (guess == number)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
      }
      remainingGuesses--;
      return null;
   }
   
   @PostConstruct
   public void reset()
   {
      this.smallest = 0;
      this.guess = 0;
      this.remainingGuesses = 10;
      this.number = manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random
>(){});
   }
   
}

Beim translator-Beispiel werden die von Ihnen eingegebenen Sätze ins Lateinische übersetzt.

Das translator-Beispiel ist eine ear und enthält EJBs. Als Folge ist seine Struktur komplexer als die desnumberguess-Beispiels.

Werfen wir zunächst einen Blick auf den ear-Aggregator, das sich im webbeans-translator-ear-Modul befindet. Maven generiert automatisch die application.xml für uns:


<plugin>
   <groupId
>org.apache.maven.plugins</groupId>
   <artifactId
>maven-ear-plugin</artifactId>
   <configuration>
      <modules>
         <webModule>
            <groupId
>org.jboss.webbeans.examples.translator</groupId>
            <artifactId
>webbeans-translator-war</artifactId>
            <contextRoot
>/webbeans-translator</contextRoot>
         </webModule>
      </modules>
   </configuration>
</plugin
>

Hier setzen wir den Kontextpfad, der uns eine schöne url liefert (http://localhost:8080/webbeans-translator).

Tipp

Falls Sie zur Generierung dieser Dateien nicht Maven verwendet haben, benötigen Sie META-INF/application.xml:


<?xml version="1.0" encoding="UTF-8"?>
<application 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/application_5.xsd"
             version="5">
  <display-name
>webbeans-translator-ear</display-name>
  <description
>Ear Example for the reference implementation of JSR 299: Web Beans</description>
  
  <module>
    <web>
      <web-uri
>webbeans-translator.war</web-uri>
      <context-root
>/webbeans-translator</context-root>
    </web>
  </module>
  <module>
    <ejb
>webbeans-translator.jar</ejb>
  </module>
</application
>

Next, lets look at the war. Just as in the numberguess example, we have a faces-config.xml (to enable Facelets) and a web.xml (to enable JSF) in WebContent/WEB-INF.

Interessanter ist das zur Übersetzung des Texts verwendete Facelet. Ganz wie im numberguess-Beispiel besitzen wir eine Vorlage, die das Formular umgibt (hier der Kürze wegen weggelassen):


<h:form id="NumberGuessMain">
            
   <table>
      <tr align="center" style="font-weight: bold" >
         <td>
            Your text
         </td>
         <td>
            Translation
         </td>
      </tr>
      <tr>
         <td>
            <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80" />
         </td>
         <td>
            <h:outputText value="#{translator.translatedText}" />
         </td>
      </tr>
   </table>
   <div>
      <h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
   </div>
   
</h:form
>

Der Benutzer kann Text im Textbereich links eingeben und dann die translate-Schaltfläche drücken (zur Übersetzung), um auf der rechten Seite das Ergebnis zu sehen.

Sehen wir uns schließlich noch das ejb-Modul webbeans-translator-ejb an. In src/main/resources/META-INF existiert nur eine leere web-beans.xml, die dazu dient das Archiv als Web Beans enthaltend zu markieren.

Wir haben uns das Interessanteste bis zuletzt aufgehoben, nämlich den Code! Das Projekt besitzt zwei einfache Beans, SentenceParser und TextTranslator und zwei Enterprise Beans, TranslatorControllerBean und SentenceTranslator. Sie sind wahrscheinlich schon weitehend vertraut damit, wie Web Bean aussehen, daher gehen wir hier nur auf die interessantesten Aspekte ein.

Sowohl bei SentenceParser als auch bei TextTranslator handelt es sich um abhängige Beans und TextTranslator verwendet Konstruktor-Initialisierung :

public class TextTranslator { 

   private SentenceParser sentenceParser; 
   private Translator sentenceTranslator; 
   
   @Initializer
   TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) 
   { 
      this.sentenceParser = sentenceParser; 
      this.sentenceTranslator = sentenceTranslator;

TextTranslator ist ein stateless Bean (mit einem lokalen Business-Interface), wo alles passiert - natürlich konnten wir keinen kompletten Übersetzer entwickeln,, aber wir haben uns Mühe gegeben!

Schließlich gibt es noch den UI-orientierten Kontroller, der den Text vom Benutzer nimmt und ihn an den translator (Übersetzer) weitergibt. Hierbei handelt es sich um ein anfragenbegrenztes, benanntes, stateful Session Bean, das den translator einspeist.

@Stateful

@RequestScoped
@Named("translator")
public class TranslatorControllerBean implements TranslatorController
{
   
   @Current TextTranslator translator;

Das Bean besitzt auch Getter und Setter für alle Felder auf der Seite.

Da es sich um ein stateful Session Bean handelt, müssen wir eine remove-Methode besitzen:

   @Remove

   public void remove()
   {
      
   }

Der Web Beans Manager ruft die remove-Methode für Sie auf, wenn das Bean gelöscht wird, in diesem Fall am Ende der Anfrage.

That concludes our short tour of the Web Beans examples. For more on Web Beans , or to help out, please visit http://www.seamframework.org/WebBeans/Development.

Wir brauche Unterstützung auf allen Gebieten - Fehlerbehebung, Schreiben neuer Features, Schreiben neuer Beispiele und bei der Übersetzung dieses Referenzhandbuchs.

Web Beans unterstützt drei primäre Mechanismen für "Dependency"-Einspeisung:

Konstruktorparameter-Einspeisung:

public class Checkout {

        
    private final ShoppingCart cart;
    
    @Initializer
    public Checkout(ShoppingCart cart) {
        this.cart = cart;
    }
}

Initializer-Methode Parameter-Einspeisung:

public class Checkout {

        
    private ShoppingCart cart;
    @Initializer 
    void setShoppingCart(ShoppingCart cart) {
        this.cart = cart;
    }
    
}

Und direkte Feldeinspeisung:

public class Checkout {


    private @Current ShoppingCart cart;
    
}

Dependency-Einspeisung findet stets bei der ersten Instantiierung der Web Bean Instanz statt.

  • Zuerst ruft der Web Bean Manager den Web Bean Konstruktor auf, um eine Instanz des Web Beans zu erhalten.

  • Als nächstes initialisiert der Web Bean Manager die Werte aller eingespeisten Felder des Web Beans.

  • Anschließend ruft der Web Bean Manager alle Initialisierermethoden des Web Beans auf.

  • Zuletzt wird die @PostConstruct-Methode des Web Bean, falls vorhanden, aufgerufen.

Die Einspeisung von Konstruktorparametern wird für EJB-Beans nicht unterstützt, da das EJB durch den EJB-Container und nicht den Web Bean Manager instantiiert wird.

Parameter von Konstruktoren und Initialisierermethoden müssen nicht explizit annotiert werden, wenn der standardmäßige Binding-Typ @Current gilt.Eingespeiste Felder jedoch müssen einen Binding-Typ festlegen, selbst wenn der standardmäßige Binding-Typ gilt. Legt das Feld keinen standardmäßige Binding-Typ fest, so wird es nicht eingespeist.

Producer-Methoden unterstützen Parametereinspeisung ebenfalls:

@Produces Checkout createCheckout(ShoppingCart cart) {

    return new Checkout(cart);
}

Observer-Methoden (auf die wir in Kapitel 9, Ereignisse näher eingehen), "Disposal"-Methoden und "Destructor"-Methoden unterstützen allesamt die Parametereinspeisung.

Die Web Beans Spezifikation definiert eine Prozedur namens typesicherer Auflösungsalgorithmus (sog. typesafe resolution algorithm), den der Web Bean Manager bei der Identifizierung des an einem Einspeisungspunkt einzuspeisenden Web Beans folgt. Dieser Algorithmus sieht auf den ersten Blick recht komplex aus, ist es aber nach kurzer Eingewöhnung nicht. Typensichere Auflösung wird zum Initialisierungszeitpunkt des Systems durchgeführt, was bedeutet, dass der Manager den Benutzer sofort darüber informiert, falls die Abhängigkeiten eines Web Beans nicht erfüllt werden können - dies erfolgt durch Meldung von UnsatisfiedDependencyException oder AmbiguousDependencyException.

Der Zweck dieses Algorithmus ist es, mehreren Web Beans die Einspeisung desselben API-Typs zu gestatten und entweder:

  • Dem Client mittels Binding-Annotationen zu gestatten auszuwählen, welche Implemetierung er benötigt,

  • Dem Anwendungs-Deployer durch Aktivierung oder Deaktivierung von Deployment-Typen gestatten auszuwählen, welche Implementierung die passende für eine bestimmte Umgebung ist, ohne dass es zu Änderungen am Client kommt oder

  • Einer Implementierung eines API mittels Deployment-Typ Präzedenz ("Deployment Type Precedence") gestatten, zum Deployment-Zeitpunkt eine andere Implementerung desselben API außer Kraft zu setzen, ohne dass dies zu Änderungen am Client führt..

Schauen wir uns jetzt näher an, wie der Web Beans Manager ein einzuspeisendes Web Bean bestimmt.

Falls mehr als ein Web Bean existiert, das einen bestimmten API-Typ implementiert, so kann der Einspeisungspunkt genau festlegen welches Web Bean eingespeist wird mittels Binding-Annotation. Zum Beispiel können zwei Implementierungen von PaymentProcessor vorhanden sein:

@PayByCheque

public class ChequePaymentProcessor implements PaymentProcessor {
    public void process(Payment payment) { ... }
}
@PayByCreditCard

public class CreditCardPaymentProcessor implements PaymentProcessor {
    public void process(Payment payment) { ... }
}

Wo @PayByCheque und @PayByCreditCard Binding-Annotationen sind:

@Retention(RUNTIME)

@Target({TYPE, METHOD, FIELD, PARAMETER})
@BindingType
public @interface PayByCheque {}
@Retention(RUNTIME)

@Target({TYPE, METHOD, FIELD, PARAMETER})
@BindingType
public @interface PayByCreditCard {}

Ein Client Web Bean Entwickler verwendet die Binding-Annotation um genau festzulegen, welches Web Bean eingespeist werden sollte.

Verwendung der Feldeinspeisung:

@PayByCheque PaymentProcessor chequePaymentProcessor;

@PayByCreditCard PaymentProcessor creditCardPaymentProcessor;

Verwendung der Initialisierermethoden-Einspeisung:

@Initializer

public void setPaymentProcessors(@PayByCheque PaymentProcessor chequePaymentProcessor, 
                                 @PayByCreditCard PaymentProcessor creditCardPaymentProcessor) {
   this.chequePaymentProcessor = chequePaymentProcessor;
   this.creditCardPaymentProcessor = creditCardPaymentProcessor;
}

Oder Verwendung der Konstruktoreinspeisung:

@Initializer

public Checkout(@PayByCheque PaymentProcessor chequePaymentProcessor, 
                @PayByCreditCard PaymentProcessor creditCardPaymentProcessor) {
   this.chequePaymentProcessor = chequePaymentProcessor;
   this.creditCardPaymentProcessor = creditCardPaymentProcessor;
}

Alle Web Beans besitzen einen Deployment-Typ. Jeder Deployment-Typ identifiziert einen Satz von Web Beans mit Vorbehalt in einigen Deployments des Systems installiert werden sollten.

Zum Beispiel könnten wir einen Deployment-Typ namens @Mock definieren, der Web Beans identifiziert, die nur installiert werden sollen, wenn das System innerhalb einer Integrationstestumgebung ausgeführt wird:

@Retention(RUNTIME)

  @Target({TYPE, METHOD})
  @DeploymentType
  public @interface Mock {}

Nehmen wir an, wir hätten ein Web Bean, das mit einem externen System interagiert, um Zahlungen zu bearbeiten:

public class ExternalPaymentProcessor {

        
    public void process(Payment p) {
        ...
    }
    
}

Da dieses Web Bean nicht explizit einen Deployment-Typ festlegt gilt der standardmäßige Deployment-Typ @Production.

Für Integration oder das Testen von Einheiten ist das externe System langsam oder nicht verfügbar. Daher würden wir ein "Mock"-Objekt erstellen:

@Mock 

public class MockPaymentProcessor implements PaymentProcessor {
    @Override
    public void process(Payment p) {
        p.setSuccessful(true);
    }
}

Wie aber bestimmt der Web Bean Manager, welche Implementierung in einem bestimmten Deployment verwendet werden soll?

Wenn Sie aufgepasst haben, fragen Sie sich jetzt wahrscheinlich, wie der Web Bean Manager entscheidet, welche Implementierung — ExternalPaymentProcessor oder MockPaymentProcessor — er wählt. Überlegen Sie sich, was passiert, wenn der Manager auf diesen Einspeisungspunkt trifft:

@Current PaymentProcessor paymentProcessor

Es gibt jetzt zwei Web Beans, die den PaymentProcessor-Vertrag erfüllen. Natürlich können wir keine Binding-Annotation zur eindeutig Machung verwenden, da Binding-Annotationen in die Quelle am Einspeisungspunkt hardcodiert und wir wollen, dass der Manager zum Deployment-Zeotpunkt entscheiden können soll!

Die Lösung dieses Problems ist, dass jeder Deployment-Typ eine andere Präzendenz besitzt. Die Präzendenz der Deployment-Typen wird durch die Reihenfolge, in der sie in web-beans.xml erscheinen, festgelegt. In unserem Beispiel erscheint @Mock später als @Production, so dass es eine höhere Präzendenz besitzt.

Findet der Manager mehr als ein Web Bean, das den von einem Einspeisungspunkt festgelegten Vertrag erfüllt (API-Typ plus Binding-Annotationen), so gilt die relative Präzedenz der Web Beans. Besitzt eines eine höhere Präzedenz als andere, so wird es für die Einspeisung gewählt. In unserem Beispiel speist der Web Bean Manager also MockPaymentProcessor bei der Ausführung unserer Integrationstestumgebung aus (und das ist es auch, was wir möchten).

Es ist interessant dies mit den heutzutage beliebten Manager Architekturen zu vergleichen. Verschiedene "leichtgewichtige" Container gestatten uns auch das bedingte Deployment von im Klassenpfad existierenden Klassen, aber Klassen, die deployt werden sollen müssen explizit, individuell im Konfigurationscode oder einer XML-Konfigurationsdatei aufgeführt sein. Web Beans unterstützt die Web Bean Definition und Konfiguration via XML, aber im gängigen Fall, in dem keine komplexe Konfiguration erforderlich ist, gestatten Deployment-Types die Aktivierung eines gesamten Satzes von Web Beans mittels einer einzigen XML-Zeile. Währenddessen kann ein den Code durchsehender Entwickler leicht einsehen, in welchen Deployment-Szenarien das Web Bean eingesetzt wird.

Clients eines eingespeisten Web Beans enthalten in der Regel keinen direkten Verweis an eine Web Bean Instanz.

Stellen wir uns vor, ein an den Geltungsbereich der Anwendung gebundenes Web Bean hielte einen direkten Verweis auf ein an den Geltungsbereich der Anfrage gebundenes Web Bean. Das an den Geltungsbereich der Anwendung gebundene Web Bean wird von vielen verschiedenen Anfragen geteilt. Jedoch sollte jede Anfrage eine andere Instanz des an den Geltungsbereich der Anfrage gebundenen Web Beans sehen!

Stellen Sie sich nun vor das an den Geltungsbereich der Session gebundene Web Bean hielte einen direkten Verweis auf ein an den Geltungsbereich der Anwendung gebundenes Web Bean. FVon Zeit zu Zeit wird der Session Kontext auf Disk serialisiert, um den Speicher effizienter zu nutzen. Die durch den Geltungsbereich der Anwendung begrenzte Instanz des Web Beans sollte jedoch nicht mit dem durch den Geltungsbereich der Session begrenzetn Web Bean serialisiert werden!

Daher muss der Web Bean Manageralle eingespeisten Verweise auf das Web Bean durch ein Proxy-Objekt einleiten, wenn das Web Bean nicht den Standard-Geltungsbereich @Dependent besitzt. Dieser Client-Proxy ist verantwortlich dafür sicher zu stellen, dass die einen Methodenaufruf erhaltende Web Bean Instanz, die mit dem aktuellen Kontext assoziierte ist. Der Client-Proxy gestattet außerdem die Serialisierung auf Disk von an Kontexte gebundenen Web Beans, ohne dassrekursiv andere eingespeiste Web Beans serialisiert werden.

Leider können aufgrund von Einschränkungen von Java einige Java-Typen nicht vom Web Bean Manager geproxiet werden. Daher meldet der Web Bean Manager eine UnproxyableDependencyException, wenn der Typ eines Einspeisungspunkts nicht geproxiet werden kann.

Die folgenden Java-Typen können nicht durch den Web Bean Manager geproxiet werden:

Es ist in der Regel ganz leicht eine UnproxyableDependencyException zu beheben. Fügen Sie der eingespeisten Klasse einfach einen Konstruktor ohne Parameters hinzu, führen Sie ein Interface ein oder ändern Sie den Gelstungsbereich des eingespeisten Web Bean zu @Dependent.

Die Anwendung kann durch Einspeisung eine Instanz des Interface Manager erhalten:

@Current Manager manager;

Das Manager-Objekt liefert einen Satz von Methoden zum programmatischen Erhalt einer Web Bean Instanz.

PaymentProcessor p = manager.getInstanceByType(PaymentProcessor.class);

Binding-Annotationen können durch Subklassifizierung der Helferklasse AnnotationLiteral festgelegt werden, da es ansonsten schwierig ist, einen Annotationstyp in Java zu instantiieren.

PaymentProcessor p = manager.getInstanceByType(PaymentProcessor.class, 

                                               new AnnotationLiteral<CreditCard
>(){});

Besitzt der Binding-Typ ein Annotationsmitglied, so können wir keine anonyme Unterklasse von AnnotationLiteral — verwenden - stattdessen werden wir eine benannte Unterklasse erstellen müssen:

abstract class CreditCardBinding 

    extends AnnotationLiteral<CreditCard
> 
    implements CreditCard {}
PaymentProcessor p = manager.getInstanceByType(PaymentProcessor.class, 

                                               new CreditCardBinding() { 
                                                   public void value() { return paymentType; } 
                                               } );

Es gibt bestimmte Arten abhängiger Objekte — Web Beans mit Geltungsbereich @Dependent — die etwas über das Objekt oder den Einspeisungspunkt in die sie eingespeist werden wissen müssen, um ihre Aufgabe zu erledigen. Zum Beispiel:

Ein Web Bean mit Geltungsbereich @Dependent kann eine Instanz von InjectionPoint einspeisen und auf Metadaten zugreifen, die mit dem zugehörigen Einspeisungspunkt zu tun haben.

Sehen wir uns ein Beispiel an. Der folgende Code ist umfangreich und empfänglich für Refaktorierungsprobleme:

Logger log = Logger.getLogger(MyClass.class.getName());

Diese schlaue kleine Producer-Methode gestattet die Einspeisung eines JDK Logger, ohne dass explizit eine Protokollkategorie festgelegt werden müsste:

class LogFactory {


   @Produces Logger createLogger(InjectionPoint injectionPoint) { 
      return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); 
   }
}

Wir können jetzt schreiben:

@Current Logger log;

Sie sind noch nicht ganz überzeugt? Dann sehen Sie sich ein weiteres Beispiel an. Zur Einspeisung von HTTP-Parametern müssen wir einen Binding-Typ festlegen:

@BindingType

@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpParam {
   @NonBinding public String value();
}

Wir würden diesen Binding-Typ an Einspeisungspunkten wie folgt verwenden:

@HttpParam("username") String username;

@HttpParam("password") String password;

Die folgende Producer-Methode erledigt die Arbeit:

class HttpParams


   @Produces @HttpParam("")
   String getParamValue(ServletRequest request, InjectionPoint ip) {
      return request.getParameter(ip.getAnnotation(HttpParam.class).value());
   }
}

(Beachten Sie, dass das value()-Mitglied der HttpParam-Annotation vom Web Bean Manager wird, da es mit @NonBinding. annotiert ist)

Der Web Bean Manager liefert ein eingebautes Web Bean, das das InjectionPoint-Interface implementiert:

public interface InjectionPoint { 

   public Object getInstance(); 
   public Bean<?> getBean(); 
   public Member getMember(): 
   public <extends Annotation
> T getAnnotation(Class<T
> annotation); 
   public Set<extends Annotation
> getAnnotations(); 
}

Bis jetzt haben wir ein paar Beispiele von Geltungsbereichtyp-Annotationen gesehen. Der Geltungsbereich eines Web Beans bestimmt den Lebenszyklus der Instanzen des Web Beans. Der Geltungsbereich bestimmt auch, welche Clients sich auf welche Instanzen des Web Beans beziehen. Gemäß der Web Beans Spezifikation bestimmt ein Geltungsbereich:

  • Wann eine neue Instanz eines beliebigen Web Beans mit diesem Geltungsbereich erstellt wird

  • Wenn eine bestehende Instanz eines beliebigen Web Beans mit diesem Geltungsbereich gelöscht wird

  • Welche eingespeisten Referenzen auf eine beliebige Instanz eines Web Beans mit diesem Geltungsbereich verweisen

Wenn wir etwa ein session-begrenztes Web Bean CurrentUser haben, so sehen alle Web Beans, die im Kontext derselben HttpSession aufgerufen werden, dieselbe Instanz von CurrentUser. Diese Instanz wird automatisch erstellt, wenn CurrentUser erstmals in dieser Session benötigt wird und automatisch gelöscht, wenn die Session endet.

Der Web Beans Geltungsbereich der Konversation ähnelt dem herkömmlichen Geltungsbereich der Session dahingehend, dass er den mit einem Benutzer des Systems assoziierten Status verwahrt und mehrere Anfragen zum Server umfasst. Anders als für den Geltungsbereich der Session gilt für den Geltungsbereich der Konversation jedoch:

Eine Konversation repräsentiert aus Perspektive des Benutzers eine Aufgabe, eine Arbeitseinheit. Der Konversationskontext enthält den Status dessen, woran der Benutzer gerade arbeitet. Arbeitet der Benutzer gleichzeitig an mehreren Dingen, so existieren mehrere Konversationen.

Der Konversation skontext ist während jeder JSF-Anfrage aktiv. Jedoch werden die meisten Konversationen am Ende der Anfrage gelöscht. Soll eine Konversation den Status über mehrere Anfragen hinweg verwahren, so muss sie explizit zu einer lange laufenden Konversation fortgepflanzt werden.

Web Beans liefert ein eingebautes Web Bean für die Steuerung des Lebenszyklus von Konversationen in einer JSF-Applikation. Dieses Web Bean kann durch Einspeisung erhalten werden:

@Current Conversation Konversation;

Um die mit der aktuellen Anfrage assoziierte Konversation an eine lange laufende Konversation fortzupflanzen, rufen Sie die begin()-Methode vom Applikationscode auf. Um den aktuellen, lange laufenden Konversationskontext für die Löschung am Ende der aktuellen Anfrage zu terminieren, rufen Sie end() auf.

IIm folgenden Beispiel steuert ein konversationsbegrenztes Web Bean die Konversation, mit der es assoziiert ist:

@ConversationScoped @Stateful

public class OrderBuilder {
    private Order order;
    private @Current Conversation conversation;
    private @PersistenceContext(type=EXTENDED) EntityManager em;
    
    @Produces public Order getOrder() {
        return order;
    }
    public Order createOrder() {
        order = new Order();
        conversation.begin();
        return order;
    }
    
    public void addLineItem(Product product, int quantity) {
        order.add( new LineItem(product, quantity) );
    }
    public void saveOrder(Order order) {
        em.persist(order);
        conversation.end();
    }
    
    @Remove
    public void destroy() {}
    
}

Dieses Web Bean ist in der Lage, seinen eigenen Lebenszyklus durch Verwendung der Conversation-API zu steuern. Aber einige andere Web Beans besitzen einen Lebenszyklus, der komplett von einem anderen Objekt abhängt.

Neben den vier eingebauten Geltungsbereichen bieten Web Beans den sogenanntenabhängigen Pseudo-Geltungsbereich. Dies ist der standardmäßige Geltungsbereich für ein Web Bean, das nicht expliziet einen Typ von Geltungsbereich deklariert.

Zum Beispiel besitzt dieses Web Bean den Geltungsbereich-Typ @Dependent:

public class Calculator { ... }

Wenn der Einspeisungspunkt eines Web Bean zu einem abhängigen Web Bean hin aufgelöst wird, so wird jedes Mal, wenn das erste Web Bean instantiiert wird, eine neue Instanz des abhängigen Web Beans erstellt. Instanzen abhängiger Web Beans werden nie von unterschiedlichen Web Beans oder unterschiedlichen Einspeisungspunkten geteilt. Sie sind abhängige Objekte einer anderen Web Bean Instanz.

Abhängige Web Bean Instanzen werden gelöscht, wenn die Instanz von der sie abhängen gelöscht wird.

Web Beans machen es einfach, eine unabhängige Instanz einer Java-Klasse oder eines EJB-Beans zu erhalten, selbst wenn die Klasse oder das EJB-Bean bereits als ein Web Bean mit einem anderen Typ von Geltungsbereich deklariert sind.

Producer-Methoden gestatten es uns, bestimmte Beschränkungen zu umgehen, die auftreten, wenn der Web Bean Manager statt die Anwendung für die Instantiierung von Objekten verantwortlich ist. Sie sind auch die einfachste Art der Integration von Objekten in die Web Beans Umgebung, die keine Web Beans sind. (In Kapitel 12, Definition von Web Beans unter Verwendung von XML lernen wir eine zweite Weise kennen.)

Gemäß der Spezifikation:

Eine Web Beans Producer-Methode fungiert als Quelle einzuspeisender Objekte wenn:

  • die einzuspeisenden Objekte keine Instanzen von Web Beans sein müssen,

  • der konkrete Typ einzuspeisender Objekte zur Runtime variieren kann oder

  • die Objekte eine bestimmte angepasste Initialisierung erfordern, die nicht vom Web Bean Konstruktor durchgeführt wird

Producer-Methoden lassen uns zum Beispiel:

  • eine JPA-Entity als ein Web Bean darlegen,

  • eine beliebige JDK-Klasse als ein Web Bean darlegen,

  • mehrere Web Beans mit unterschiedlichen Geltungsbereichen oder Initialisierung für diesselbe Implementierungsklasse definieren oder

  • die Implementierung eines API-Typs zur Runtime variieren.

Insbesondere lassen uns Producer-Methoden Runtime-Polymorphie mit Web Beans verwenden. Wie wir bereits gesehen haben sind Deployment-Typen eine leistungsfähige Lösung zum Problem der Polymorphie zum Zeitpunkt des Deployment. Aber nachdem das System deployt ist, wird die Web Bean Implementierung behoben. Eine Producer-Methode besitzt keine solche Einschränkung:

@SessionScoped

public class Preferences {
    
    private PaymentStrategyType paymentStrategy;
    
    ...
    
    @Produces @Preferred 
    public PaymentStrategy getPaymentStrategy() {
        switch (paymentStrategy) {
            case CREDIT_CARD: return new CreditCardPaymentStrategy();
            case CHEQUE: return new ChequePaymentStrategy();
            case PAYPAL: return new PayPalPaymentStrategy();
            default: return null;
        } 
    }
    
}

Überlegen Sie einen Einspeisungspunkt:

@Preferred PaymentStrategy paymentStrat;

Dieser Einspeisungspunkt besitzt denselben Typ und diesselben Binding-Annotationen wie die Producer-Methode, so dass er unter Verwendung der üblichen Web Beans Einspeisungsregeln zur Producer-Methode auflöst. Die Producer-Methode wird vom Web Bean Manager aufgerufen um eine Instanz zu erhalten, um diesen Einspeisungspunkt zu bedienen.

.

Es gibt ein potenzielles Problem mit dem Code oben. Die Implementierungen von CreditCardPaymentStrategy werden unter Verwendung des Java new Operators instantiiert. Direkt durch die Anwendung instantiierte Objekte können die Dependency-Einspeisung nicht nutzen und besitzen keine Interzeptoren.

Falls dies nicht das ist was wir wünschen, so können wir Dependency-Einspeisung in die Producer-Methode verwenden, um Web Bean Instanzen zu erhalten:

@Produces @Preferred @SessionScoped

public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps,
                                          ChequePaymentStrategy cps,
                                          PayPalPaymentStrategy ppps) {
    switch (paymentStrategy) {
        case CREDIT_CARD: return ccps;
        case CHEQUE: return cps;
        case PAYPAL: return ppps;
        default: return null;
    } 
}

Aber Moment mal, was wenn CreditCardPaymentStrategy ein anfragenbegrenztes Web Bean ist? Dann hat die Producer-Methode die Wirkung, dass Sie die aktuelle anfragenbegrenzte Instanz in den Geltungsbereich der Session "befördert". Das ist mit ziemlicher Sicherheit ein Fehler! Das anfragenbegrenzte Objekt wird vom Web Bean Manager gelöscht ehe die Session endet, aber der Verweis auf das Objekt bleibt im Geltungsbereich der Session "hängen" in the session scope. Dieser Fehler wird nicht vom Web Bean Manager aufgespürt, daher seien Sie besonders vorsichtig wenn Sie Web Bean Instanzen von Producer-Methoden wiedergeben!

Es existieren mindestens drei Arten, wie dieser Fehler behoben werden kann. Wir könnten den Geltungsbereich der CreditCardPaymentStrategy-Implementierung ändern, aber das würde auch andere Clients dieses Web Beans betreffen. Eine bessere Option wäre es, den Geltungsbereich der Producer-Methode auf @Dependent oder @RequestScoped zu ändern.

Eine gängigere Lösung ist es jedoch, die spezielle @New Binding-Annotation zu verwenden.

Das erste wichtige Thema von Web Beans ist Loose Coupling (lose Paarung). Wir haben bereits drei Wege gesehen, diese lose Paarung zu erreichen:

Diese Techniken dienen der Aktivierung der losen Paarung ("Loose Coupling") von Client und Server. Der Client ist nicht mehr eng an eine API-Implementierung gebunden und muss den Lebenszyklus des Server-Objekts nicht mehr verwalten. Dadurch können Objekte, die "stateful" sind, interagieren als seien Sie Dienste .

Lose Paarung macht ein System dynamischer. Das System kann auf gut definierte Weise auf Änderungen reagieren. In der Vergangenheit war es der Fall, dass Frameworks die versuchten die obigen Facilities bereitzustellen, dies auf Kosten der Typensicherheit taten. Bei Web Beans handelt es sich um die erste Technologie, die diese Ebene der losen Paarung auf typensichere Weise ermöglicht.

Web Beans bieten drei weitere wichtige Facilities, die das Ziel loser Paarung weiterbringen:

Sehen wir uns zunächst die Interzeptoren an.

Web Beans verwenden die grundlegende Interzeptor-Architektur von EJB 3.0, wobei die Funktionalität in zwei Richtungen erweitert wird:

  • Jedes Web Bean kann Interzeptoren besitzen, nicht nur Session Beans.

  • Web Beans bieten eine fortgeschrittenere auf Annotationen basierende Vorgehensweise bei der Bindung von Interzeptoren an Web Beans.

Die EJB-Spezifikation definiert zwei Arten von Abfangpunkten (sog. "Interception Points"):

  • Business Methoden Interception und

  • Lebenszyklus-Callback Interception.

Ein Business Methoden Interzeptor gilt für Aufrufe von Methoden des Web Beans durch Clients des Web Beans:

public class TransactionInterceptor {

    @AroundInvoke public Object manageTransaction(InvocationContext ctx) { ... }
}

Ein Lebenszyklus Callback-Interzeptor gilt für Aufrufe von Lebenszyklus Callbacks durch den Container:

public class DependencyInjectionInterceptor {

    @PostConstruct public void injectDependencies(InvocationContext ctx) { ... }
}

Eine Interzeptorklasse kann sowohl Lebenszyklus-Callbacks als auch Business-Methoden abfangen.

Interzeptoren bieten eine leistungsfähige Weise, Probleme, die orthogonal zum Typensystem sind, festzuhalten und zu trennen. Jeder Interzeptor kann Aufrufe jedes Java Typs abfangen. Dies macht ihn perfekt für die Lösung technischer Probleme wie etwa Transaktionsmanagement und Sicherheit.Jedoch sind Interzeptoren ihrem Wesen nach nicht der tatsächlichen Semantik der Ereignisse gewahr, die sie abfangen. Interzeptoren sind daher nicht die geeigneten Tools zur Separierung von unternehmensbezogenen Problemen.

Das Gegenteil gilt für Dekoratoren. Ein Dekorator fängt Aufrufe nur für ein bestimmtes Java-Interface ab und kennt daher die zu diesem Interface gehörende Semantik. Dadurch sind Dekoratoren das perfekte Tool zur Bearbeitung einige unternehmensbezogener Probleme. Es bedeutet auch, dass Dekoratoren nicht diesselbe Allgemeingültigkeit wie Interzeptoren besitzen. Dekoratoren können keine technischen Probleme lösen, die sich über viele disparate Typen verteilen.

Nehmen wir an, wir besitzen ein Konten repräsentierendes Interface:

public interface Account {

    public BigDecimal getBalance();
    public User getOwner();
    public void withdraw(BigDecimal amount);
    public void deposit(BigDecimal amount);
}

Mehrere verschiedene Web Beans in unserem System implementieren das Account-Interface. Es existiert allerdings eine gängige legale Voraussetzung die besagt, dass für jede Art von Konto, große Transaktionen vom System in einem besonderen Protokoll gespeichert werden müssen. Dies ist die perfekte Aufgabe für einen Dekorator.

Ein Dekorator ist ein einfaches Web Bean, das den Typ das es dekoriert implementiert und @Decorator annotiert ist.

@Decorator

public abstract class LargeTransactionDecorator 
        implements Account {
    
    @Decorates Account account;
    
    @PersistenceContext EntityManager em;
    
    public void withdraw(BigDecimal amount) {
        account.withdraw(amount);
        if ( amount.compareTo(LARGE_AMOUNT)
>0 ) {
            em.persist( new LoggedWithdrawl(amount) );
        }
    }
    
    public void deposit(BigDecimal amount);
        account.deposit(amount);
        if ( amount.compareTo(LARGE_AMOUNT)
>0 ) {
            em.persist( new LoggedDeposit(amount) );
        }
    }
    
}

Anders als andere einfache Web Beans, kann ein Dekorator eine abstrakte Klasse sein. Falls es nichts besonderes ist, dass der Dekorator für eine bestimmte Methode des dekorierten Interface tun muss, so brauchen Sie diese Methode nicht zu implementieren.

Die Web Beans Ereignisbenachrichtigungs-Facility gestattet es Web Beans auf eine völlig abgekoppelte Weise zu interagieren. Ereignis Producer bringen Ereignisse auf, die dann vom Web Bean Manager an Ereignis Observer geliefert werden. Dieses schlichte Schema klingt zwar etwas nach dem bekannten Observer/observierbar Muster, aber es gibt ein paar Überraschungen:

  • nicht nur sind Ereignis-Producer von Observern abgekoppelt, Observer sind auch komplett von Producern abgekoppelt,

  • Observer können eine Kombination von "Selektoren" festlegen, um den Satz von Ereignisbenachrichtigungen einzugrenzen, die sie erhalten und

  • Observer können sofort benachrichtigt werden oder sie können festlegen, dass die Lieferung des Ereignisses bis zum Abschluss der aktuellen Transaktion verschoben wird

Der Ereignis-Producer kann ein Ereignisbenachrichtigungs-Objekt durch Einspeisung erhalten:

@Observable Event<Document

> documentEvent

Die @Observable-Annotation definiert implizit ein Web Bean mit Geltungsbereich @Dependent und Deployment-Typ @Standard mit einer durch den Web Bean Manager bereitgestellten Implementierung.

Ein Producer bringt durch Aufruf der fire()-Methode des Event-Interface Ereignisse auf, wobei ein Ereignisobjekt weitergegeben wird:

documentEvent.fire(document);

Ein Ereignis-Objekt kann eine Instanz einer beliebigen Java-Klasse sein, die keine Typ-Variablen oder Platzhalter-Typenparameter besitzt. Das Ereignis wird an jede Observer-Methode geliefert, die:

Der Web Bean Manager ruft einfach alle Observer-Methoden auf und gibt das Ereignis-Objekt als den Wert des Ereignisparameters weiter. Meldet eine Observer-Methode eine Ausnahme, so stoppt der Web Bean Manager den Aufruf von Observer-Methoden und die Ausnahme wird durch die fire()-Methode erneut gemeldet.

Um einen "Selektor" festzulegen kann der Ereignis-Producer eine Instanz des Ereignis-Binding-Typs an die fire()-Methode weitergeben:

documentEvent.fire( document, new AnnotationLiteral<Updated

>(){} );

Die Helferklasse AnnotationLiteral ermöglicht die Instanziierung der Binding-Typen inline, da es andernfalls schwierig ist, die in Java zu tun.

Das Ereignis wird an jede Observer-Methode geliefert, die:

Alternativ können Ereignis-Bindings durch Festlegen des Einspeisungspunkts der Ereignisbenachrichtigung festgelegt werden:

@Observable @Updated Event<Document

> documentUpdatedEvent

Dann besitzt jedes über diese Instanz abgegebene Ereignis das Event annotierte Ereignis-Binding. Das Ereignis wird an jede Observer-Methode geliefert, die:

Transaktionale Observers erhalten ihre Ereignisbenachrichtigungen vor oder nach der Abschlussphase der Transaktion während derer das Ereignis aufgegekommen ist. Zum Beispiel muss die folgende Observer-Methode einen Satz von Abfrageergebnissen neu laden, der im Applikationskontext gecacht ist, jedoch nur dann, wenn die den Category-Baum aktualisierenden Transaktionen erfolgreich sind:

public void refreshCategoryTree(@AfterTransactionSuccess @Observes CategoryUpdateEvent event) { ... }

Es gibt drei Arten von transaktionalen Observern:

Transaktional Observer sind in einem "stateful" Objektmodell wie Web Beans sehr wichtig, da der Status oft länger bestehen bleibt als eine einzelne atomare Transaktion.

Stellen wir uns vor, wir besitzen einen gecachten Satz von JPA-Abfrageergebnissen im Geltungsbereich der Anwendung:

@ApplicationScoped @Singleton

public class Catalog {
    @PersistenceContext EntityManager em;
    
    List<Product
> products;
    @Produces @Catalog 
    List<Product
> getCatalog() {
        if (products==null) {
            products = em.createQuery("select p from Product p where p.deleted = false")
                .getResultList();
        }
        return products;
    }
    
}

Von Zeit zu Zeit wird ein Product erstellt oder gelöscht. Ist dies der Fall, so müssen wir den Product-Katalog neu laden. Wir sollten damit aber bis nach dem erfolgreichen Abschluss der Transaktion warten!

Das Web Bean, das Products erstellt oder löscht könnte Ereignisse aufrufen, zum Beispiel:

@Stateless

public class ProductManager {
    @PersistenceContext EntityManager em;
    @Observable Event<Product
> productEvent;
    public void delete(Product product) {
        em.delete(product);
        productEvent.fire(product, new AnnotationLiteral<Deleted
>(){});
    }
    
    public void persist(Product product) {
        em.persist(product);
        productEvent.fire(product, new AnnotationLiteral<Created
>(){});
    }
    
    ...
    
}

Und jetzt kann Catalog die Ereignisse nach erfolgreichem Abschluss der Transaktion beobachten:

@ApplicationScoped @Singleton

public class Catalog {
    ...
    
    void addProduct(@AfterTransactionSuccess @Observes @Created Product product) {
        products.add(product);
    }
    
    void addProduct(@AfterTransactionSuccess @Observes @Deleted Product product) {
        products.remove(product);
    }
    
}

Das zweite wichtige Thema von Web Beans ist starke Typisierung (sog. "strong Typing"). Die Informationen zu Abhängigkeiten, Interzeptoren und Dekoratoren eines Web Beans und die Informationen zu Ereigniskonsumenten (Event Consumers) für einen Ereignis-Producer sind in typensicheren Java-Konstrukten enthalten, die vom Kompilierer (Compiler) validiert werden können.

Sie sehen keine String-basierten Bezeichner in Web Beans Code; dies ist nicht der Fall weil das Framework diese unter Verwendung irgendwelcher Defaulting-Regeln — vor Ihnen verbirgt; sogenannte "Konfiguration nach Konvention" — sondern weil einfach keine Strings existieren!

Der offensichtliche Vorteil dieser Vorgehensweise ist, dass jede IDE Auto-Completion, Validierung und Refaktorierung ohne die Notwendigkeit spezieller Tools bereitstellen kann. Es existiert jedoch noch ein weiterer, nicht sofort ersichtlicher Vorteil. Es stellt sich nämlich heraus, dass Sie - wenn Sie über die Identifizierung von Objekten, Ereignissen oder Interzeptoren via Annotationen statt Namen nachdenken - Sie Gelegenheit haben, die semantische Ebene Ihres Code anzuheben.

Web Beans soll dazu ermutigen Annotationen zu entwickeln, die Konzepte formen, etwa

statt Namen wie Assoziationsbegriffe wie

Die Annotationen sind wiederverwendbar. Sie helfen bei der Beschreibung gängiger Eigenschaften verschiedener Teile des Systems. Sie helfen uns bei der Kategorisierung und dem Verständnis unseres Codes. Sie helfen uns dabei auf gängige Weise mit gängigen Problemen umzugehen. Sie machen unseren Code leichter lesbar und einfacher zu verstehen.

Web Beans Stereotypen erweitern diese Idee um einen Schritt. Ein Stereotyp formt eine gängige Rolle in Ihrer Anwendungsarchitektur. Es enthält verschiedene Eigenschaften der Rolle, einschließlich deren Geltungsbereich, Interzeptorbindungen, Deployment-Typ usw. in einem einzelnen, wiederverwendbaren Paket.

Sogar Web Beans XML Metadaten sind stark typisiert! Es gibt keinen Kompilierer für XML, daher nutzen Web Beans XML-Schemas zur Validierung der in XML vorkommenden Java-Typen und Attribute. Diese Vorgehensweise führt zur besseren Lesbarkeit der XML, ebenso wie Annotationen unseren Java Code einfacher lesbar machten.

Wir können jetzt einige fortgeschrittenere Features von Web Beans kennenlernen. Vergessen Sie nicht, dass diese Features unseren Code sowohl einfacher zu validieren als auch leserlicher machen sollen. Meist werden Sie diese Features nicht verwenden müssen, wenn Sie dies aber auf kluge Weise tun, so werden Sie deren Vorteile schnell zu schätzen wissen.

Gemäß der Web Beans Spezifikation:

In vielen Systemen produziert die Verwendung architektonischer Muster einen Satz wiederkehrender Web Bean Rollen. Ein Stereotyp gestattet dem Entwickler eines Frameworks die Identifizierung einer solchen Rolle und die Deklaration einiger gemeinsamer Metadaten für Web Beans mit dieser Rolle an einer zentralen Stelle.

Ein Stereotyp beinhaltet eine beliebige Kombination von:

  • einem standardmäßigen Deployment-Typ,

  • einem standardmäßigen Geltungsbereich-Typ,

  • einer Einschränkung hinsichtlich des Geltungsbereichs des Web Beans,

  • einer Anforderung, dass das Web Bean einen bestimmten Typ implementiert oder erweitert und

  • einem Satz von Interzeptor Binding Annotationen.

Ein Stereotyp kann auch festlegen, dass alle Web Beans mit dem Stereotyp standardmäßige Web Bean Namen besitzen.

Ein Web Bean kann null, ein oder mehrere Stereotypen deklarieren.

Bei einem Stereotyp handelt es sich um einen Java Annotationstyp. Dieses Stereotyp identifiziert Action-Klassen in einem MVC-Framework:

@Retention(RUNTIME)

@Target(TYPE)
@Stereotype
public @interface Action {}

Wir verwenden das Stereotyp durch Anwendung der Annotation an einem Web Bean.

@Action 

public class LoginAction { ... }

Wir haben bereits gesehen, wie das Web Beans Modell zur Dependency Einspeisung uns die Außerkraftsetzung der Implementierung eines API zum Zeitpunkt des Deployment gestattet. Das folgende Enterprise Web Bean zum Beispiel liefert eine Implementierung der API PaymentProcessor in Production:

@CreditCard @Stateless

public class CreditCardPaymentProcessor 
        implements PaymentProcessor {
    ...
}

Aber in unserer Staging-Umgebung setzen wir diese Implementierung von PaymentProcessor mit einem anderen Web Bean außer Kraft:

@CreditCard @Stateless @Staging

public class StagingCreditCardPaymentProcessor 
        implements PaymentProcessor {
    ...
}

Wir haben bei StagingCreditCardPaymentProcessor versucht, AsyncPaymentProcessor in einem bestimmten Deployment des Systems komplett zu ersetzen. In diesem Deployment, hätte der Deployment Typ @Staging eine höhere Priorität als der standardmäßige Deployment Typ @Production und daher Clients mit dem folgenden Einspeisungspunkt:

@CreditCard PaymentProcessor ccpp

Wir würden eine Instanz von StagingCreditCardPaymentProcessor erhalten.

Leider könnten wir in gleich mehrere Fallen tappen:

  • Das Web Bean mit der höheren Priorität implementiert möglicherweise nicht alle API-Typen des Web Beans, das es außer Kraft zu setzen versucht,

  • Das Web Bean mit der höheren Priorität deklariert möglicherweise nicht alle Binding-Typen des Web Beans, das es außer Kraft zu setzen versucht,

  • Das Web Bean mit der höheren Priorität besitzt möglicherweise nicht denselben Namen wie das Web Bean, das es außer Kraft zu setzen versucht oder

  • das Web Bean, das es außer Kraft zu setzen versucht deklariert möglicherweise eine Producer Methode, eine Bereinigungsmethode odereine Observer Methode.

In allen diesen Fällen kann das Web Bean, das wir außer Kraft zu setzen versucht haben, nach wie vor zur Runtime aufgerufen werden. Daher ist Außerkraftsetzung anfällig für Entwicklerfehler.

Web Beans bieten ein spezielles Feature namens Specialization (Spezialisierung), das dem Entwickler hilft, diese Stolperfallen zu umgehen. Specialization wirkt auf den ersten Blick etwas ungewöhnlich, ist aber in der Praxis einfach zu verwenden und Sie werden die zusätzliche Sicherheit, die es bietet bald schätzen.

Bis jetzt haben wir viele Beispiele von unter Verwendung von Annotationen deklarierten Web Beans gesehen. Es gibt jedoch ein paar Fälle, in denen keine Annotationen zur Definition des Web Beans verwendet werden können:

  • Wenn die Implementierungsklasse von einer bereits bestehenden Bibliothek stammt oder

  • wenn mehrere Web Beans mit derselben Implementierungsklasse existieren sollten.

In jedem dieser Fälle bieten uns Web Beans zwei Optionen:

  • das Schreiben einer Producer-Methode oder

  • das Deklarieren des Web Beans mittels XML.

Viele Frameworks verwenden XML zur Bereitstellung von Metadaten, die sich auf Java-Klassen beziehen. Web Beans jedoch verwenden eine sehr unterschiedliche Herangehensweise bei der Festlegung von Namen von Java-Klassen, Feldern oder Methoden als andere Frameworks. Statt dem Schreiben von Klassen- und Mitglieder-Namen als String-Werte von XML-Elementen und Attributen, gestatten Web Beans die Verwendung des Klassen- und Mitglieder-Namens als Name des XML-Elements.

Der Vorteil bei dieser Vorgehensweise ist, dass Sie ein XML-Schema schreiben können, dass Rechtschreibfehler in Ihrem XML-Dokument verhindert. Es ist sogar möglich, dass ein Tool das XML-Schema automatisch aus dem kompilierten Java-Code generiert. Oder eine integrierte Entwicklungsumgebung könnte dieselbe Validierung durchführen, ohne dass der explizite Generierungsschritt notwendig wäre.

Das dritte Thema von Web Beans ist die Integration. Web Beans wurden derart entwickelt, dass sie mit anderer Technologie zusammenarbeiten und dem Anwendungsentwickler dabei helfen, diese andere Technologie zusammenzufügen. Bei Web Beans handelt es sich um offene Technologie. Sie bilden einen Teil des Java EE Ökosystems und sind selbst die Grundlage für ein neues Ökosystem portabler Erweiterungen und Integration mit bestehenden Frameworks und bestehender Technologie.

Wir haben bereits gesehen, wie Web Beans bei der Integration von EJB und JSF helfen, indem sie gestatten, dass EJBs direkt an JSF-Seiten gebunden werden. Das ist nur der Anfang. Web Beans bieten dasselbe Potential zur Diversifizierung anderer Technologien, wie etwa Business Process Management Engines, anderer Web Frameworks und Komponentenmodellen Dritter. Die Java EE Plattform wird nie zur Standardisierung aller interessanter Technologien in der Lage sein, die bei der Entwicklung von Java-Anwendungen verwendet werden, aber Web Beans vereinfachen die nahtlose Verwendung solcher Technologien, die noch nicht Teil der Plattform sind, innerhalb einer Java EE Umgebung.

Wir wollen Ihnen jetzt zeigen, wie Sie die Java EE platform in einer Web Beans verwendenden Anwendung am besten nutzen. Wir sehen uns auch kurz einen Satz von SPIs an, die portable Erweiterungen zu Web Beans unterstützen sollen. Sie werden diese SPIs vielleicht nie direkt benutzen müssen, aber es ist hilfreich diese zu kennen, falls Sie sie einmal brauchen. Primär ist wichtig, dass Sie diese bei jeder Verwendung von Erweiterungen Dritter indirekt nutzen können.

Web Beans sind voll in die Java EE Umgebung integriert. Web Beans besitzen Zugriff auf Java EE Resourcen und JPA Persistenzkontexte. Sie können in Unified EL Ausdrücken in JSF- und JSP-Seiten verwendet werden. Sie können sogar in einige Objekte eingespeist werden, etwa Servlets and Message-Driven Beans, die keine Web Beans sind.

Das Versenden von Nachrichten unter Verwendung von JMS kann aufgrund der Anzahl verschiedener Objekte mit denen Sie zu tun haben recht komplex sein. Für Warteschlangen haben wir Queue, QueueConnectionFactory, QueueConnection, QueueSession und QueueSender. Für Topics haben wir Topic, TopicConnectionFactory, TopicConnection, TopicSession und TopicPublisher. Jedes dieser Objekte besitzt einen eigenen Lebenszyklus und ein eigenes Threading-Modell, das unsere Aufmerksamkeit erfordert.

Web Beans übernehmen all das für uns. Das Einzige, was wir tun müssen ist unsere Warteschlange oder unser Topic in web-beans.xml zu deklarieren und einen assoziierten Binding-Typ und eine Connection-Factory festzulegen.


<Queue>
    <destination
>java:comp/env/jms/OrderQueue</destination>
    <connectionFactory
>java:comp/env/jms/QueueConnectionFactory</connectionFactory>
    <myapp:OrderProcessor/>    
</Queue
>

<Topic>
    <destination
>java:comp/env/jms/StockPrices</destination>
    <connectionFactory
>java:comp/env/jms/TopicConnectionFactory</connectionFactory>
    <myapp:StockPrices/>    
</Topic
>

Jetzt können wir einfach Queue, QueueConnection, QueueSession oder QueueSender für eine Warteschlange oder aber Topic, TopicConnection, TopicSession oder TopicPublisher für ein Topic einspeisen.

@OrderProcessor QueueSender orderSender;

@OrderProcessor QueueSession orderSession;
public void sendMessage() {
    MapMessage msg = orderSession.createMapMessage();
    ...
    orderSender.send(msg);
}
@StockPrices TopicPublisher pricePublisher;

@StockPrices TopicSession priceSession;
public void sendMessage(String price) {
    pricePublisher.send( priceSession.createTextMessage(price) );
}

Der Lebenszyklus der eingespeisten JMS-Objekte wird komplett durch den Web Bean Manager gesteuert.

Web Beans sind als Plattform für Frameworks, Erweiterungen und Integration mit anderer Technologie vorgesehen. Web Beans bieten daher einen Satz von SPIs für den Gebrauch durch Entwickler übertragbarer Erweiterungen zu Web Beans. Die folgenden Arten von Erweiterungen zum Beispiel wurden von den Designern von Web Beans vorgesehen:

  • Integration mit Business Process Management Engines,

  • Integration mit den Frameworks Dritter, wie etwa Spring, Seam, GWT oder Wicket und

  • neue, auf dem Web Beans Programmiermodell basierende Technologie.

Der zentrale Kern zur Erweiterung von Web Beans ist das Manager-Objekt.

Das Manager-Interface die programmatische Registrierung und den Erhalt von Web Beans, Interzeptoren, Dekoratoren, Observern und Kontexten.

public interface Manager

{
   public <T
> Set<Bean<T
>
> resolveByType(Class<T
> type, Annotation... bindings);
   public <T
> Set<Bean<T
>
> resolveByType(TypeLiteral<T
> apiType,
         Annotation... bindings);
   public <T
> T getInstanceByType(Class<T
> type, Annotation... bindings);
   public <T
> T getInstanceByType(TypeLiteral<T
> type,
         Annotation... bindings);
   public Set<Bean<?>
> resolveByName(String name);
   public Object getInstanceByName(String name);
   public <T
> T getInstance(Bean<T
> bean);
   public void fireEvent(Object event, Annotation... bindings);
   public Context getContext(Class<? extends Annotation
> scopeType);
   public Manager addContext(Context context);
   public Manager addBean(Bean<?> bean);
   public Manager addInterceptor(Interceptor interceptor);
   public Manager addDecorator(Decorator decorator);
   public <T
> Manager addObserver(Observer<T
> observer, Class<T
> eventType,
         Annotation... bindings);
   public <T
> Manager addObserver(Observer<T
> observer, TypeLiteral<T
> eventType,
         Annotation... bindings);
   public <T
> Manager removeObserver(Observer<T
> observer, Class<T
> eventType,
         Annotation... bindings);
   public <T
> Manager removeObserver(Observer<T
> observer,
         TypeLiteral<T
> eventType, Annotation... bindings);
   public <T
> Set<Observer<T
>
> resolveObservers(T event, Annotation... bindings);
   public List<Interceptor
> resolveInterceptors(InterceptionType type,
         Annotation... interceptorBindings);
   public List<Decorator
> resolveDecorators(Set<Class<?>
> types,
         Annotation... bindings);
}

Wir können eine Instanz von Manager via Einspeisung erhalten:

@Current Manager Manager

Instanzen der abstrakten Klasse Bean repräsentieren Web Beans. Für jedes Web Bean in der Anwendung wird eine Instanz von Bean mit dem Manager-Objekt registriert.

public abstract class Bean<T> {

    
    private final Manager manager;
    
    protected Bean(Manager manager) {
        this.manager=manager;
    }
    
    protected Manager getManager() {
        return manager;
    }
    
    public abstract Set<Class> getTypes();
    public abstract Set<Annotation> getBindingTypes();
    public abstract Class<? extends Annotation> getScopeType();
    public abstract Class<? extends Annotation> getDeploymentType(); 
    public abstract String getName();
    
    public abstract boolean isSerializable();
    public abstract boolean isNullable();
    public abstract T create();
    public abstract void destroy(T instance);
    
}

Es ist möglich, die Bean-Klasse zu erweitern und Instanzen durch Aufruf von Manager.addBean() zu registrieren, um Support für neue Arten von Web Beans zu bieten, neben denen, die durch die Web Beans Spezifikation definiert sind (einfache und Enterprise Web Beans, Producer Methoden und JMS Endpunkte). Zum Beispiel könnten wir die Bean-Klasse verwenden, um zu ermöglichen, dass durch ein anderes Framework gemanagte Objekte in Web Beans eingespeist werden.

Durch die Web Beans Spezifikation werden zwei Unterklassen von Bean definiert: Interceptor und Decorator.

Derzeit läuft die Web Beans RI nur in JBoss AS 5; die Implementierung der RI in andere EE-Umgebungen (zum Beispiel einen anderen Applikationsserver wie Glassfish) in einen Servlet-Container (wie Tomcat) oder eine Embedded EJB3.1 Implementierung ist recht einfach. In diesem Anhang gehen wir kurz auf die notwendigen Schritte ein.

Das Web Beans SPI befindet sich im webbeans-ri-spi-Modul und ist als webbeans-ri-spi.jar verpackt. Einige SPIs sind optional, wenn Sie das standardmäßige Verhalten außer Kraft setzen möchten, sind andere erforderlich.

Alle Interfaces im SPI unterstützen das Dekorator-Muster und liefern eine Forwarding-Klasse.

Die Web Beans RI delegiert auch EJB3 Bean Discovery an den Container, so dass er nicht nach EJB3-Annotationen scannen oder ejb-jar.xml parsen muss. Für jedes EJB in der Anwendung sollte der EJBDescriptor aufgefunden werden:

public interface EjbDiscovery

{
   public static final String PROPERTY_NAME = EjbDiscovery.class.getName();
   
   /**
    * Gets a descriptor for each EJB in the application
    * 
    * @return The bean class to descriptor map 
    */
   public Iterable<EjbDescriptor<?>
> discoverEjbs();
   
}
public interface EjbDescriptor<T

> {
   
   /**
    * Gets the EJB type
    * 
    * @return The EJB Bean class
    */
   public Class<T
> getType();
   /**
    * Gets the local business interfaces of the EJB
    * 
    * @return An iterator over the local business interfaces
    */
   public Iterable<BusinessInterfaceDescriptor<?>
> getLocalBusinessInterfaces();
   
   /**
    * Gets the remote business interfaces of the EJB
    * 
    * @return An iterator over the remote business interfaces
    */
   public Iterable<BusinessInterfaceDescriptor<?>
> getRemoteBusinessInterfaces();
   
   /**
    * Get the remove methods of the EJB
    * 
    * @return An iterator over the remove methods
    */
   public Iterable<Method
> getRemoveMethods();
   /**
    * Indicates if the bean is stateless
    * 
    * @return True if stateless, false otherwise
    */
   public boolean isStateless();
   /**
    * Indicates if the bean is a EJB 3.1 Singleton
    * 
    * @return True if the bean is a singleton, false otherwise
    */
   public boolean isSingleton();
   /**
    * Indicates if the EJB is stateful
    * 
    * @return True if the bean is stateful, false otherwise
    */
   public boolean isStateful();
   /**
    * Indicates if the EJB is and MDB
    * 
    * @return True if the bean is an MDB, false otherwise
    */
   public boolean isMessageDriven();
   /**
    * Gets the EJB name
    * 
    * @return The name
    */
   public String getEjbName();
   
   
}

Der EjbDescriptor ist recht leicht verständlich und sollte relevante Metadaten wie in der EJB-Spezifikation definiert wiedergeben. Neben diesen beiden Interfaces existiert ein BusinessInterfaceDescriptor, der ein lokales Business-Interface repräsentiert (die Interface-Klasse und den für die Suche einer Instanz des EJB verwendeten jndi-Namens enthaltend).

The Web Beans RI must delegate JTA activities to the container. The SPI provides a couple hooks to easily achieve this with the TransactionServices interface.

public interface TransactionServices

{
   /**
    * Possible status conditions for a transaction. This can be used by SPI
    * providers to keep track for which status an observer is used.
    */
   public static enum Status
   {
      ALL, SUCCESS, FAILURE
   }
   /**
    * Registers a synchronization object with the currently executing
    * transaction.
    * 
    * @see javax.transaction.Synchronization
    * @param synchronizedObserver
    */
   public void registerSynchronization(Synchronization synchronizedObserver);
   /**
    * Queries the status of the current execution to see if a transaction is
    * currently active.
    * 
    * @return true if a transaction is active
    */
   public boolean isTransactionActive();
}

The enumeration Status is a convenience for implementors to be able to keep track of whether a synchronization is supposed to notify an observer only when the transaction is successful, or after a failure, or regardless of the status of the transaction.

Any javax.transaction.Synchronization implementation may be passed to the registerSynchronization() method and the SPI implementation should immediately register the synchronization with the JTA transaction manager used for the EJBs.

To make it easier to determine whether or not a transaction is currently active for the requesting thread, the isTransactionActive() method can be used. The SPI implementation should query the same JTA transaction manager used for the EJBs.

Das org.jboss.webbeans.bootstrap.api.Bootstrap-Interface definiert den Bootstrap für Web Beans. Um Web Beans zu booten müssen Sie eine Instanz von org.jboss.webbeans.bootstrap.WebBeansBootstrap erhalten (die Boostrap implementiert), diese über die verwendeten SPIs informieren und dann beim Container um Start anfragen.

Der Bootstrap ist in Phasen aufgeteilt, Bootstrap Initialisierung und Bootstrap. Die Initialisierung erstellt einen Manager und fügt die Standard-Kontexte (spezifikationsdefiniert) hinzu. Bootstrap findet EJBs, Klassen und XML auf; fügt unter Verwendung von Annotationen definierte Beans hinzu; fügt unter Verwendung von XML definierte Beans hinzu; und validiert alle Beans.

Zur Initialisierung des Bootstrap rufen Sie Bootstrap.initialize() auf. Ehe Sie initialize() aufrufen, müssen Sie Bootstrap.setEjbResolver() aufgerufen haben. Falls Sie nicht den eingebauten DefaultNamingContext oder den eingebauten DefaultResourceLoader verwenden, so müssen Sie diese setzen, ehe Sie initialize() aufrufen.

Nach Aufruf von initialize() erhalten Sie den Manager durch Aufruf von Bootstrap.getManager().

Zum Booten des Containers rufen Sie Bootstrap.boot() auf. Ehe Sie boot() aufrufen, müssen Sie Bootstrap.setWebBeanDiscovery(), Bootstrap.setEjbDiscovery() und Bootstrap.setApplicationContext() aufgerufen haben.

Um den Container herunterzufahren, rufen Sie you call Bootstrap.shutdown() auf. Dies gestattet es dem Container notwendige Bereinigungsvorgänge durchzuführen.

Es gibt eine Reihe von Voraussetzungen, die Web Beans RI dem Container für das korrekte Funktionieren von Implementierungen auferlegen, die außerhalb von Implementierung von APIs fallen.

Klassenlader-Isolierung

Falls Sie die Web Beans RI in eine Umgebung integrieren, die das Deployment mehrerer Anwendungen unterstützt, so müssen Sie automatisch oder über Benutzerkonfiguration die Klassenlader-Isolierung für jede Web Beans Anwendung aktivieren.

Servlet listener and filters

Falls Sie Web Beans in eine Servlet Umgebung integrieren, müssen Sie org.jboss.webbeans.servlet.WebBeansListener als einen Servlet-Listener registrieren, entweder automatisch oder aber durch Benutzerkonfiguration. Dies muss für jede Servlet benutzende Web Beans Applikation erfolgen.

If you are integrating the Web Beans into a JSF environment you must register org.jboss.webbeans.servlet.ConversationPropagationFilter as a Servlet listener, either automatically, or through user configuration, for each Web Beans application which uses JSF. This filter can be registered for all Servlet deployment safely.

Session Bean Interzeptor

Falls Sie Web Beans in eine EJB Umgebung integrieren, müssen Sie org.jboss.webbeans.ejb.SessionBeanInterceptor als einen EJB-Interzeptor für alle EJBs in der Applikation registrieren, entweder automatisch oder aber durch Benutzerkonfiguration. Dies muss für jede Enterprise Beans benutzende Web Beans Applikation erfolgen.

Die webbeans-ri.jar

Falls Sie Web Beans in eine Umgebung integrieren, die das Deployment von Anwendungen unterstützt, so müssen Sie die webbeans-ri.jar in den isolierten Klassenlader der Anwendungen einfügen. Das Laden kann nicht aus einem geteilten Klassenlader erfolgen.