EJB 3.0 auf den Punkt gebracht

Trotz mehrerer positiver Aspekte behindert die Komplexität der Enterprise JavaBeans-Architektur die Einführung von J2EE. Die EJB-Architektur ist wahrscheinlich die einzige J2EE-Komponente, die das Versprechen von J2EE, die Entwicklerproduktivität durch eine einfache Entwicklung zu steigern, so kläglich erfüllt hat. EJB 3.0 unternimmt einen weiteren Versuch, dieses Versprechen zu erfüllen, indem die Komplexität von EJB für Entwickler verringert wird. EJB 3.0 verringert die Anzahl der Programmierartefakte, die Entwickler bereitstellen müssen, eliminiert oder minimiert die zu implementierenden Rückrufmethoden und verringert die Komplexität des Entity-Bean-Programmiermodells und des O / R-Mapping-Modells.

In diesem Artikel werde ich zunächst die wichtigsten Änderungen in EJB 3.0 behandeln. Es ist wichtig, dass die Grundlagen vorhanden sind, bevor Sie in den EJB 3.0-Pool eintauchen. Als Nächstes gebe ich einen allgemeinen Überblick über den EJB 3.0-Entwurf und gehe dann auf die Einzelheiten der vorgeschlagenen Spezifikation ein, wobei ich alle Änderungen einzeln beachte: Auswirkungen auf Arten von Enterprise-Beans, O / R-Mapping-Modell, Entity- Beziehungsmodell, EJB QL (EJB Query Language) usw.

Hintergrund

Die beiden wichtigsten Änderungen in der vorgeschlagenen EJB 3.0-Spezifikation sind die Verwendung der in Java 5 eingeführten Programmanmerkungsfunktion und des neuen O / R-Mapping-Modells, das auf Hibernate basiert.

Metadatenfunktion in Java 5

Java 5 (früher J2SE 1.5 oder Tiger genannt) hat eine neue Programmanmerkungsfunktion für die Sprache eingeführt. Mit dieser Funktion können Sie benutzerdefinierte Anmerkungen definieren und anschließend Felder, Methoden, Klassen usw. mit diesen Anmerkungen versehen. Anmerkungen wirken sich nicht direkt auf die Programmsemantik aus, aber Tools (Kompilierungszeit oder Laufzeit) können diese Anmerkungen überprüfen, um zusätzliche Konstrukte (wie einen Bereitstellungsdeskriptor) zu generieren oder das gewünschte Laufzeitverhalten zu erzwingen (wie die Stateful-Natur einer EJB-Komponente). Anmerkungen können durch Quellanalyse (z. B. Compiler oder IDE-Tools) oder mithilfe der in Java 5 hinzugefügten zusätzlichen Reflection-APIs überprüft werden. Anmerkungen können so definiert werden, dass sie nur auf Quellcodeebene, auf kompilierter Klassenebene oder zur Laufzeit verfügbar sind . Alle im frühen Entwurf RetentionPolicyvon EJB 3.0 vorgeschlagenen Anmerkungen haben eine vonRUNTIME. Dies erhöht den Speicherbedarf der Klasse geringfügig, erleichtert jedoch das Leben von Container- und Tool-Anbietern erheblich.

Weitere Informationen zu diesem Thema finden Sie unter Ressourcen.

Überwintern

Hibernate ist ein beliebtes Open-Source-O / R-Mapping-Framework für Java-Umgebungen, das Entwickler vor den häufigsten Programmieraufgaben im Zusammenhang mit Datenpersistenz schützen soll. Es hat auch eine spezielle Hibernate Query Language (HQL), deren Abdrücke in der neuen EJB-QL zu sehen sind. Hibernate bietet Funktionen zum Abrufen und Aktualisieren von Daten, zum Verbindungspooling, zum Transaktionsmanagement, zum Management deklarativer Entitätsbeziehungen sowie für deklarative und programmatische Abfragen.

Vogelperspektive

Die Änderungen in der vorgeschlagenen EJB 3.0-Spezifikation können in zwei Kategorien unterteilt werden:

  • Ein auf Anmerkungen basierendes EJB-Programmiermodell, zusätzlich zum EJB 2.1-Modell zur Definition des Verhaltens einer Anwendung über Bereitstellungsdeskriptoren und mehrere Schnittstellen.
  • Das neue Persistenzmodell für Entity Beans. EJB QL hat sich ebenfalls erheblich verändert.

Diese Vorschläge haben auch mehrere Nebenwirkungen, wie ein neues Client-Programmiermodell, die Verwendung von Geschäftsschnittstellen und einen Entity-Bean-Lebenszyklus. Bitte beachten Sie, dass das EJB 2.1-Programmiermodell (mit Deployment-Deskriptoren und Home / Remote-Schnittstellen) weiterhin gültig ist. Das neue vereinfachte Modell ersetzt das EJB 2.1-Modell nicht vollständig.

EJB-Anmerkungen

Eines der wichtigsten Ziele der Expertengruppe ist es, die Anzahl der Artefakte zu reduzieren, die ein Bohnenanbieter bereitstellen muss, und die Gruppe hat bei der Erreichung dieses Ziels gute Arbeit geleistet. In der EJB 3.0-Welt sind alle Arten von Enterprise-Beans nur alte Java-Objekte (POJO) mit entsprechenden Anmerkungen. Mit Anmerkungen können die Geschäftsschnittstelle der Bean, O / R-Zuordnungsinformationen, Ressourcenreferenzen und fast alles andere definiert werden, was über Bereitstellungsdeskriptoren oder -schnittstellen in EJB 2.1 definiert wurde. Bereitstellungsdeskriptoren sind nicht mehr erforderlich. Die Home-Schnittstelle ist nicht mehr vorhanden, und Sie müssen nicht unbedingt eine Business-Schnittstelle implementieren (der Container kann sie für Sie generieren).

Beispielsweise deklarieren Sie eine zustandslose Session-Bean mithilfe der @StatelessAnmerkung zur Java-Klasse. Bei Stateful Beans wird die @RemoveAnnotation für eine bestimmte Methode markiert, um anzugeben, dass die Bean-Instanz nach Abschluss eines Aufrufs der markierten Methode entfernt werden soll.

Um die Menge an Informationen zu reduzieren, die Sie für eine Komponente angeben müssen, hat die Expertengruppe einen Ansatz für die Konfiguration nach Ausnahmen gewählt. Dies bedeutet, dass Sie intuitive Standardeinstellungen für alle Anmerkungen bereitstellen, damit die meisten allgemeinen Informationen abgeleitet werden können.

Das neue Persistenzmodell

Die neuen Entity-Beans sind ebenfalls nur POJOs mit einigen Anmerkungen und von Geburt an keine dauerhaften Entitäten. Eine Entitätsinstanz wird persistent, sobald sie mit einem verknüpft ist EntityManagerund Teil eines Persistenzkontexts wird . Ein Persistenzkontext ist lose gleichbedeutend mit einem Transaktionskontext. in strengen Worten, es koexistiert implizit mit dem Umfang einer Transaktion.

Die Entitätsbeziehungen werden auch durch Anmerkungen definiert. Darüber hinaus erfolgt die O / R-Zuordnung auch über Anmerkungen, und es werden mehrere datenbankspezifische Vorgänge unterstützt. Mit EJB 2.1 verwendeten Entwickler ihre eigenen Entwurfsmuster oder verwendeten nicht portierbare Techniken (z. B. Strategien zur automatischen Schlüsselgenerierung).

Tief graben

Es ist jetzt an der Zeit, sich mit den Einzelheiten der Vorschläge zu befassen, die im frühen Entwurf von EJB 3.0 gemacht wurden. Beginnen wir mit allen vier Arten von Enterprise-Beans und fahren wir dann mit den allgemeinen Vorschlägen für das gesamte EJB-Programmiermodell fort.

Zustandslose Session Beans:

Eine zustandslose Session Bean (SLSB), die nach EJB 3.0 geschrieben wurde, ist nur eine einfache Java-Datei mit einer Annotation auf Klassenebene von @Stateless. Die Bean-Klasse kann die javax.ejb.SessionBeanSchnittstelle implementieren , ist jedoch nicht erforderlich (und wird dies normalerweise nicht tun).

Ein SLSB hat keine Home-Schnittstelle mehr - tatsächlich erfordert es kein EJB-Typ. Die Bean-Klasse kann eine Geschäftsschnittstelle implementieren oder nicht. Wenn keine Geschäftsschnittstellen implementiert werden, wird eine Geschäftsschnittstelle mit allen öffentlichen Methoden generiert. Wenn nur bestimmte Methoden in der Geschäftsschnittstelle verfügbar gemacht werden sollen, können alle diese Methoden mit der @BusinessMethodAnmerkung gekennzeichnet werden. Standardmäßig sind alle generierten Schnittstellen lokal, aber die @RemoteAnmerkung kann verwendet werden, um anzugeben, dass eine Remote-Schnittstelle generiert werden soll.

Die folgenden Codezeilen reichen aus, um eine HelloWorldBean zu definieren . Mit EJB 2.1 hätte dieselbe Bean mindestens zwei Schnittstellen, eine Implementierungsklasse mit mehreren leeren Methodenimplementierungen und einen Bereitstellungsdeskriptor benötigt.

import javax.ejb. *; / ** * Eine zustandslose Session-Bean, die die Generierung einer Remote-Business-Schnittstelle * anfordert. * / @Stateless @Remote öffentliche Klasse HelloWorldBean {public String sayHello () {return "Hello World !!!"; }}

Unter Ressourcen finden Sie den vollständigen Quellcode, der diesem Artikel beiliegt.

Stateful Session Beans

Die Geschichte mit Stateful Session Beans (SFSB) ist für SLSB ziemlich gleich, mit Ausnahme einiger SFSB-spezifischer Punkte:

  • Ein SFSB sollte eine Möglichkeit haben, sich selbst zu initialisieren (bereitgestellt durch die ejbCreate()Methode in EJB 2.1 und früher). Die EJB 3.0-Spezifikation schlägt vor, solche Initialisierungsmethoden als benutzerdefinierte Methoden bereitzustellen und über die Geschäftsschnittstelle der Bean bereitzustellen. Die Verantwortung liegt nun beim Client, geeignete Initialisierungsmethoden aufzurufen, bevor die Bean verwendet wird. Die Expertengruppe diskutiert immer noch die Notwendigkeit, eine Anmerkung bereitzustellen, die eine bestimmte Methode für die Initialisierung kennzeichnet.
  • Der Bean-Anbieter kann jede SFSB-Methode mit der @RemoveAnnotation markieren, um anzuzeigen, dass die Bean-Instanz nach dem Aufruf der annotierten Methode entfernt werden muss. Auch hier diskutiert die Expertengruppe noch, ob eine Einrichtung erforderlich ist, um anzuzeigen, dass die Bean nicht entfernt werden darf, wenn die Methode nicht normal abgeschlossen wird.

Hier ist meine Meinung zu den beiden offenen Fragen:

  • Sollte eine Anmerkung für die Initialisierungsmethode vorhanden sein? Ich stimme mit Ja - mit der Annahme, dass der Container sicherstellt, dass mindestens eine der Initialisierungsmethoden aufgerufen wird, bevor eine andere Geschäftsmethode aufgerufen wird. Dies schützt nicht nur vor versehentlichen Programmierfehlern, sondern erhöht auch die Sicherheit des Containers bei der Wiederverwendung von SFSB-Instanzen. Lassen Sie mich der Klarheit halber hier erwähnen, dass keine bestimmten Initialisierungsmethoden (wie ejbCreate) in Betracht gezogen werden; Die Expertengruppe erwägt lediglich, eine Annotationsmarkierung als Methode für die Initialisierung zu verwenden.
  • Sollte es konfigurierbar sein, dass durch eine abnormale Beendigung der @RemoveMethode die Bean-Instanz nicht entfernt wird? Wieder ist meine Stimme ja. Dies gibt nur dem Bean-Anbieter und den Client-Programmierern eine bessere Kontrolle. Es bleibt nur eine Frage: Was passiert mit den Beans, die bei einem erfolglosen Aufruf der remove-Methode als nicht entfernt markiert sind und die remove-Methode einer bestimmten Instanz nie erfolgreich abgeschlossen wird? Es gibt keine Möglichkeit, diese Instanzen programmgesteuert zu entfernen, sie werden jedoch beim Sitzungszeitlimit entfernt.

Ein Beispiel für einen SFSB finden Sie im Quellcode.

Nachrichtengesteuerte Bohnen

Message-Driven Beans (MDBs) sind die einzige Art von Bean, die eine Geschäftsschnittstelle implementieren müssen. Der Typ dieser Schnittstelle gibt den Typ des Messaging-Systems an, das die Bean unterstützt. Für JMS-basierte MDBs (Java Message Service) ist diese Schnittstelle javax.jms.MessageListener. Beachten Sie, dass die MDB-Geschäftsschnittstelle keine echte Geschäftsschnittstelle ist , sondern lediglich eine Messaging-Schnittstelle.

Entity Beans

Entity-Beans werden mit der @EntityAnnotation markiert , und alle Eigenschaften / Felder in der Entity-Bean-Klasse, die nicht mit der @TransientAnnotation markiert sind, werden als persistent betrachtet. Persistente Entity-Bean-Felder werden über JavaBean-Eigenschaften oder nur als öffentliche / geschützte Java-Klassenfelder verfügbar gemacht.

Entity-Beans können Hilfsklassen zur Darstellung des Entity-Bean-Status verwenden, Instanzen dieser Klassen haben jedoch keine dauerhafte Identität. Stattdessen ist ihre Existenz stark an die Bean-Instanz der Eigentümerentität gebunden. Auch diese Objekte können nicht zwischen Entitäten geteilt werden.

Im Quellcode finden Sie einige Beispiele für Entity Beans.

Entitätsbeziehungen

EJB 3.0 supports both unidirectional and bidirectional relationships between entity beans, which can be one-to-one, one-to-many, many-to-one, or many-to-many relationships. However, the two sides of a bidirectional relationship are distinguished as the owning side and the inverse side. The owning side is responsible for propagating relationship changes to the database. For many-to-many associations, the owning side must be explicitly specified. Actually it's the reverse side that is specified by the isInverse=true annotation member on the reverse side's ManyToMany annotation; from that, the owning side is deduced. Now, didn't the expert group say it was making EJB easier?

O/R mapping

The O/R mapping model has also significantly changed from the abstract-persistence-schema-based approach to a Hibernate-inspired one. Though the expert group is still discussing the model, and a clear picture will emerge only with the next draft, this draft features clear indications of the overall approach.

For one, the O/R mapping will be specified in the entity bean class itself by annotations. Also, the approach is to refer to concrete tables and columns instead of the abstract persistence schema. The O/R mapping model has intrinsic support for native SQL; that is, support at a deeper level, not just the ability to run native SQL queries. For example, the column definitions annotation (@Column) has a member columnDefinition that can be something like columnDefinition="BLOB NOT NULL".

Client programming model

An EJB client can acquire a reference to the bean's business interface using the injection mechanism (@Inject annotation). Using the newly introduced @javax.ejb.EJBContext.lookup() method is another approach. But the specification is not clear as to how a standalone Java client acquires reference to a bean instance since the standalone Java clients run in a J2EE client container and lack access to the @javax.ejb.EJBContext object. There is yet another mechanism—a newly introduced universal context object: @javax.ejb.Context(). But, again, the spec does not say how this object can be used in a client container.

EJB QL

Queries can be defined through the @NamedQuery annotation. Two members of this annotation are name and queryString. Once defined, this query can be accessed using the EntityManager.createNamedQuery(name) method. You can also create a regular JDBC-style (Java Database Connectivity) query by calling EntityManager.createQuery(ejbqlString) or a native query using EntityManager.createNativeQuery(nativeSqlString).

EJB QL queries can have both positional as well as named parameters. The javax.ejb.Query interface provides methods for setting these parameters, executing updates, listing results, etc.

Here is one example of how an EJB QL query can be created and executed:

.. .. @NamedQuery (name = "findAllCustomersWithName", queryString = "SELECT c FROM Customer c WHERE c.name LIKE: custName") .. .. @Inject public EntityManager em; customers = em.createNamedQuery ("findAllCustomersWithName") .setParameter ("custName", "Smith") .listResults ();

Im Folgenden werden einige der verschiedenen Verbesserungen aufgeführt, die am QL selbst vorgenommen wurden: