Im Vergleich zu EJB 2.1 vereinfacht EJB 3.1 die Erstellung von Enterprise-Java™-Bean-Anwendungen.
EJB 2.x und Komplexität der J2EE-1.4-Architektur
Geschäftsebene: In der J2EE 1.4-Architektur werden Session-Beans verwendet,
um Geschäftslogikkomponenten einzuschließen und dadurch Services für die Transaktionsverarbeitung,
die verteilte Verarbeitung, den Fernzugriff und die Sicherheit bereitzustellen.
Sie implementieren normalerweise ein Fassadenmuster, um den Datenaustausch im Netz
zwischen dem Client und dem Service-Provider zu reduzieren.
Der Zugriff auf Session-Beans erfolgt über lokale Clients (d. h. Clients innerhalb derselben JVM) oder ferne Clients.
Message-driven Beans
werden verwendet, um externe JMS-Provider (wie MQSeries) für die Aktivierung asynchroner Nachrichtenbehandlungsservices zu integrieren.
Session-Beans
und Message-driven Beans bilden zusammen die Ebene der
Geschäftslogik. Es wird von Ebenen gesprochen,
weil Layering (Aufteilung in Ebenen) ein weiteres grundlegendes Konzept im Design dieser Unternehmensarchitektur ist, das zentrale Funktionen wie die Trennung von Aufgaben und Fähigkeiten, das Clustering
und die Wiederverwendung von Komponenten ermöglicht.
Persistenzebene:
Die zweite grundlegende Ebene ist die Persistenzebene, bei der es sich um die Services und Komponenten handelt,
die ermöglichen, dass die Anwendungsdaten in einer relationalen Datenbank persistent sind. Die Persistenzebene
kann auf die folgenden Arten implementiert werden:
- Entity-Beans (containergesteuert oder Bean-gesteuert)
- JDBC™-Datenzugriffsobjekte
- ORM-Frameworks (Object-relational Mapping, objektrelationale Zuordnung)
Probleme bei der EJB 2.x-Spezifikation
- Die EJB 2.x-Spezifikation setzt voraus, dass die Komponentenschnittstelle eine Schnittstelle aus dem EJB-Frameworkpaket erweitert
und dass die Implementierungsklasse für die Geschäftslogik
eine Schnittstelle aus dem EJB-Frameworkpaket
implementiert. Diese Voraussetzungen führen zu einer starren Verbindung
zwischen dem vom Entwickler geschriebenen Code und den Schnittstellenklassen aus
dem EJB-Frameworkpaket. Außerdem ist die Implementierung
einiger unnötiger Callback-Methoden (ejbCreate, ejbPassivate,
ejbActivate), die nicht unmittelbar dem Hauptentwurfsziel der EJB entsprechen, sowie die Verarbeitung
unnötiger Ausnahmen erforderlich.
- EJB-Implementierungsdeskriptoren sind sehr umfassend, komplex und fehleranfällig.
- EJBs sind schwierig zu testen, da die Anwendung einen J2EE-Container benötigt, um alle Services bereitzustellen, die zur ordnungsgemäßen Ausführung
der EJB-Komponente erforderlich sind.
- Wenn Sie beim Zugriff auf eine Ressource (z. B. auf eine
Datenquelle oder auf eine EJB-Home-Referenz) jedes Mal auf JNDI zurückgreifen müssen, ist dies bei der J2EE-Entwicklung eine
aufwendige Operation.
- Das CMP-Modell (Container-managed Persistence) ist komplex zu entwickeln und zu verwalten.
Vereinfachtes Modell in EJB 3.1
Die
Gesamtarchitektur von Java EE und EJB 3.1 spiegelt die Vereinfachung des EJB 3.1-Modells wider:

Das zugrunde liegende Konzept der EJB
3.1-Spezifikation basiert auf einem POJO-Programmiermodell (Plain Old Java Object),
das Java-Annotationen verwendet,
um Informationen zu erfassen, die in Implementierungsdeskriptor enthalten waren. Implementierungsdeskriptoren
sind nun in den meisten Fällen optional. Die weitgehende Verwendung von Standardwerten bedeutet zudem,
dass Sie weniger Unterstützungscode schreiben und pflegen müssen. Dies vereinfacht
die Programmierungserfahrung bei der Erstellung und Verwendung der EJB 3.1-Komponenten sehr. Dieses vereinfachte Modell hat die
folgenden Hauptfeatures:
- EJBs sind nun POJOs (Plain Old Java Objects), die
gewöhnliche Geschäftsschnittstellen (POJI) bereitstellen. Home-Schnittstellen sind nicht erforderlich.
- Es werden Metadatenannotationen und ein erweiterbares, über Metadaten gesteuertes, attributorientiertes Framework für die
Generierung von Java-Code oder XML-Implementierungsdeskriptoren
verwendet.
- Es sind keine spezifischen Schnittstellen und Implementierungsdeskriptoren mehr erforderlich.
(Implementierungsdeskriptordaten können durch Annotationen ersetzt werden.)
- Über den Interceptor werden beim Aufruf von Geschäftsmethoden oder beim Auftreten von Lebenszyklusereignissen
Benutzermethoden aufgerufen.
- Es werden nach Möglichkeit Standardwerte verwendet (Ansatz "configuration by exception" - Konfiguration bei Ausnahmen).
- Reduzierung der Anforderungen für die Verwendung geprüfter Ausnahmen.
- Es wird ein vollständig neues Persistenzmodell (auf der Basis des JPA-Standards)
verwendet, das EJB 2.x-Entity-Beans ablöst.
Tabelle 1. Vergleich der Schritte für die Erstellung von Beans in EJB
2.1 und EJB 3.1. EJB 2.x verwendet Implementierungsdeskriptoren und
EJB 3.1 verwendet Annotationen. Schritte zur Definition einer Stateless Session-Bean in EJB 2.x |
Schritte zur Definition einer Stateless Session-Bean in EJB 3.1 |
Definieren Sie die folgenden Komponenten, um eine Stateless Session-Bean
gemäß der 2.x-Spezifikation zu erstellen:
- EJB-Komponentenschnittstelle: Wird von einem EJB-Client verwendet, um Zugriff auf die
Funktionen der Bean zu erhalten. Darin sind die Geschäftsmethoden definiert.
Die Komponentenschnittstelle wird als EJB-Objekt bezeichnet. Es gibt zwei Typen von
Komponentenschnittstellen:
- Ferne Komponentenschnittstelle (EJBObject): Wird von einem fernen Client verwendet, um
über das Protokoll RMI-IIOP auf die EJB zuzugreifen.
- Lokale Komponentenschnittstelle (EJBLocalObject): Wird vom lokalen Client (der
innerhalb derselben JVM aktiv ist) verwendet, um auf die EJB zuzugreifen.
- EJB-Home-Schnittstelle: Wird von einem EJB-Client verwendet, um Zugriff auf die Bean
zu erhalten. Enthält die Lebenszyklusmethoden der Bean zur Erstellung, zur Suche und zum Entfernen.
Die Home-Schnittstelle wird als EJB-Home bezeichnet. Das Objekt "EJBHome" ist ein Objekt,
das die Home-Schnittstelle implementiert und wie in
EJBObject während der Entwicklung von Container-Tools generiert wird
und containerspezifischen Code enthält. Beim Start erstellt der EJB-Container eine Instanz
der EJBHome-Objekte der implementierten Enterprise-Beans und registriert
Home im Namensservice. Ein EJB-Client greift auf die EJBHome-Objekte unter Verwendung von
Java Naming and Directory
Interface (JNDI) zu. Es gibt zwei Typen von Home-Schnittstellen:
- Ferne Home-Schnittstelle (EJBHome): Wird von einem fernen Client verwendet, um über
das Protokoll RMI-IIOP auf die EJB zuzugreifen.
- Lokale Home-Schnittstelle (EJBLocalHome): Wird vom lokalen Client (der
innerhalb derselben JVM aktiv ist) verwendet, um auf die EJB zuzugreifen.
- EJB-Bean-Klasse: Enthält die gesamte eigentliche Geschäftslogik der Bean.
Dies ist die Klasse, die die Implementierung der Geschäftslogik bereitstellt. Methoden in dieser
Bean-Klasse sind Methoden in der Komponente und in den Home-Schnittstellen zugeordnet.
|
Definieren Sie ein POJO, um eine Stateless Session-Bean gemäß der
EJB 3.1-Spezifikation zu deklarieren:
@Stateless
public class MySessionBean implements MyBusinessInterface {
// business methods according to MyBusinessInterface
.....
}
- Wenn Sie dieselbe Bean in der fernen Schnittstelle zugänglich machen möchten, verwenden Sie die Annotation
"@Remote":
@Remote(MyRemoteBusinessInterface.class)
@Stateless
public class MyBean implements MyRemoteBusinessInterface {
// ejb methods
.....
}
|
Vergleich der EJB 2.1-Klasse samt Implementierungsdeskriptordatei mit der
entsprechenden EJB 3.1-Klasse
Die Beispiele in Tabelle 1 entsprechen sich funktional:
Tabelle 2. Vergleich von EJB
2.1 und EJB 3.1. EJB 2.1 verwendet Implementierungsdeskriptoren und
EJB 3.1 verwendet Annotationen. EJB 2.1 |
EJB 3.1 |
Java-Klasse
public class AccountBean
implements javax.ejb.SessionBean {
SessionContext ctx;
DataSource accountDB;
public void setSessionContext(SessionContext ctx) {
this.ctx = ctx;
}
public void ejbCreate() {
accountDB = (DataSource)ctx.lookup(
"jdbc/accountDB");
}
public void ejbActivate() { }
public void ejbPassivate() { }
public void ejbRemove() { }
public void setAccountDeposit(int empId,
double deposit) {
...
Connection conn = accountDB.getConnection();
...
}
...
}
|
Java-Klasse
@Stateless
public class AccountBean implements Account
{
@Resource private DataSource accountDB;
public void setAccountDeposit(int customerId,
double deposit) {
...
Connection conn = accountDB.getConnection();
...
}
...
}
|
Implementierungsdeskriptor
<session>
<ejb-name>AccountBean</ejb-name>
<local-home>AccountHome</local-home>
<local>Account</local>
<ejb-class>com.example.AccountBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<resource-ref>
<res-ref-name>jdbc/accountDB</res-ref-name>
<res-ref-type>javax.sql.DataSource</res-ref-type>
<res-auth>Container</res-auth>
</resource-ref>
</session>
...
<assembly-descriptor>...</assembly-descriptor>
|
|