6. Version 2: OpenEJB-/JPA-Architektur
6.1. Einführung in die Portierungsprinzipien
Hier stellen wir die Prinzipien vor, die für die Portierung einer JPA-/Spring-/Hibernate-Anwendung auf eine JPA-/OpenEJB-/EclipseLink-Anwendung maßgeblich sind. Wir werden bis Abschnitt 6.2 warten, um die Maven-Projekte anzulegen.
6.1.1. Die beiden Architekturen
Die aktuelle Implementierung mit Spring / Hibernate
![]() |
Die zu erstellende Implementierung mit OpenEJB / EclipseLink
![]() |
6.1.2. Projektbibliotheken
- Die [DAO]- und [Business]-Schichten werden nicht mehr von Spring instanziiert. Sie werden vom OpenEJB-Container instanziiert.
- Die Spring-Container-Bibliotheken und deren Konfiguration werden durch die OpenEJB-Container-Bibliotheken und deren Konfiguration ersetzt.
- Die Bibliotheken der JPA-/Hibernate-Schicht werden durch die der JPA-/EclipseLink-Schicht ersetzt.
6.1.3. Konfiguration der JPA-/EclipseLink-/OpenEJB-Schicht
- Die Datei [META-INF/persistence.xml], die die JPA-Schicht konfiguriert, sieht nun wie folgt aus:
- Zeile 3: Transaktionen in einem EJB-Container sind vom Typ JTA (Java Transaction API). Bei Spring waren sie vom Typ RESOURCE_LOCAL.
- Zeile 9: Die verwendete JPA-Implementierung ist EclipseLink
- Zeilen 5–7: Von der JPA-Schicht verwaltete Entitäten
- Zeilen 11–13: Eigenschaften des EclipseLink-Anbieters
- Zeile 12: Bei jeder Ausführung werden Tabellen angelegt
Die JDBC-Eigenschaften der vom OpenEJB-Container verwendeten JTA-Datenquelle werden durch die folgende Konfigurationsdatei [conf/openejb.conf] festgelegt:
- Zeile 3: Wir verwenden die ID „Default JDBC Database“, wenn wir mit einem in die Anwendung selbst eingebetteten OpenEJB-Container arbeiten.
- Zeile 5: Wir verwenden eine MySQL-Datenbank [dbpam_eclipselink]
6.1.4. Implementierung der [DAO]-Schicht unter Verwendung von EJBs
- Die Klassen, die die [DAO]-Schicht implementieren, werden zu EJBs. Nehmen wir das Beispiel der Klasse [CotisationDao]:
Die Schnittstelle [ICotisationDao] in der Spring-Version sah wie folgt aus:
Das EJB implementiert dieselbe Schnittstelle in zwei verschiedenen Formen: einer lokalen und einer entfernten. Die lokale Schnittstelle kann von einem Client verwendet werden, der in derselben JVM läuft, während die entfernte Schnittstelle von einem Client verwendet werden kann, der in einer anderen JVM läuft.
Die lokale Schnittstelle:
- Zeile 6: Die Schnittstelle [ICotisationDaoLocal] erbt von der Schnittstelle [ICotisationDao], um alle deren Methoden zu übernehmen. Sie fügt keine neuen hinzu.
- Zeile 5: Die Annotation @Local macht sie zu einer lokalen Schnittstelle für das EJB, das sie implementieren wird.
Die Remote-Schnittstelle:
- Zeile 6: Die Schnittstelle [ICotisationDaoRemote] erbt von der Schnittstelle [ICotisationDao], um alle deren Methoden zu übernehmen. Sie fügt keine neuen hinzu.
- Zeile 5: Die Annotation @Remote macht es zu einer Remote-Schnittstelle für das EJB, das sie implementieren wird.
Die [DAO]-Schicht wird von einem EJB implementiert, das beide Schnittstellen implementiert (dies ist nicht zwingend erforderlich):
- Zeile 1: die Annotation @Stateless, die die Klasse zu einem EJB macht
- Zeile 2: Die Annotation @TransactionAttribute, die sicherstellt, dass jede Methode in der Klasse innerhalb einer Transaktion ausgeführt wird.
- Zeile 5: Die Annotation @PersistenceContext, die den EntityManager der JPA-Schicht in die Klasse [CotisationDao] einfügt. Sie ist identisch mit der in der Spring-Version.
Wenn die lokale Schnittstelle der [DAO]-Schicht verwendet wird, läuft der Client dieser Schnittstelle in derselben JVM.
![]() |
Oben tauschen die [Business]- und [DAO]-Schichten Objekte per Referenz aus. Wenn eine Schicht das gemeinsam genutzte Objekt ändert, erkennt die andere Schicht diese Änderung.
Wenn die Remote-Schnittstelle der [DAO]-Schicht verwendet wird, läuft der Client dieser Schnittstelle in der Regel in einer anderen JVM.
![]() |
In der obigen Abbildung tauschen die [Business]- und [DAO]-Schichten Objekte nach Wert aus (Serialisierung des ausgetauschten Objekts). Wenn eine Schicht ein gemeinsam genutztes Objekt ändert, nimmt die andere Schicht diese Änderung nur wahr, wenn das geänderte Objekt an sie zurückgegeben wird.
6.1.5. Implementierung der [Business]-Schicht unter Verwendung eines EJB
- Die Klasse, die die [business]-Schicht implementiert, wird ebenfalls zu einem EJB, das eine lokale und eine Remote-Schnittstelle implementiert. Die ursprüngliche [IMetier]-Schnittstelle sah wie folgt aus:
Wir erstellen eine lokale Schnittstelle und eine Remote-Schnittstelle auf Basis der vorherigen Schnittstelle:
Das EJB in der [Business]-Schicht implementiert diese beiden Schnittstellen:
- Zeilen 1–2: Definieren Sie ein EJB, in dem jede Methode innerhalb einer Transaktion ausgeführt wird.
- Zeile 7: Eine Referenz auf die lokale Schnittstelle des EJB [CotisationDao].
- Zeile 6: Die Annotation @EJB weist den EJB-Container an, eine Referenz auf die lokale Schnittstelle des EJB [CotisationDao] einzufügen.
- Zeilen 8–11: Wir verfahren ebenso für die lokalen Schnittstellen der EJBs [EmployeeDao] und [CompensationDao].
Letztendlich werden bei der Instanziierung des [Metier]-EJBs die Felder in den Zeilen 7, 9 und 11 mit Verweisen auf die lokalen Schnittstellen der drei EJBs in der [DAO]-Schicht initialisiert. Wir gehen hier also davon aus, dass die [Business]- und die [DAO]-Schicht in derselben JVM ausgeführt werden.
![]() |
6.1.6. EJB-Clients
![]() |
In der obigen Abbildung muss die [ui]-Schicht, um mit der [business]-Schicht zu kommunizieren, eine Referenz auf die Remote-Schnittstelle des EJB in der [business]-Schicht abrufen.
![]() |
Im obigen Diagramm muss die [UI]-Schicht, um mit der [Business]-Schicht zu kommunizieren, eine Referenz auf die lokale Schnittstelle des EJBs der [Business]-Schicht abrufen. Die Methode zum Abrufen dieser Referenzen variiert von Container zu Container. Für den OpenEJB-Container können Sie wie folgt vorgehen:
Referenz auf die lokale Schnittstelle:
- Zeilen 2–5: Der OpenEJB-Container wird initialisiert.
- Zeile 5: Wir verfügen über einen JNDI-Kontext (Java Naming and Directory Interface), der es uns ermöglicht, Referenzen auf die EJBs abzurufen. Jedes EJB wird durch einen JNDI-Namen identifiziert:
- (Fortsetzung)
- Für die lokale Schnittstelle fügen Sie „Local“ zum EJB-Namen hinzu (Zeilen 7–9)
- Für die Remote-Schnittstelle fügen wir „Remote“ zum EJB-Namen hinzu
Bei Java EE 5 variieren diese Regeln je nach EJB-Container. Dies stellt eine Herausforderung dar. Mit Java EE 6 wurde eine JNDI-Notation eingeführt, die auf allen Anwendungsservern portabel ist.
Der vorstehende Code ruft Referenzen auf die lokalen Schnittstellen von EJBs über deren JNDI-Namen ab. Wir haben bereits erwähnt, dass diese auch über die Annotation @EJB abgerufen werden können. Daher könnten wir folgendes schreiben:
Die Annotation @EJB wird nur berücksichtigt, wenn sie zu einer Klasse gehört, die vom EJB-Container geladen wird. Dies ist beispielsweise bei der Klasse [Metier] der Fall. Der obige Code gehört jedoch zu einer Konsolenklasse, die nicht vom EJB-Container geladen wird. Wir sind daher gezwungen, die JNDI-Namen der EJBs zu verwenden.
Nachfolgend finden Sie den Code, um eine Referenz auf die Remote-Schnittstelle des [Metier]-EJBs zu erhalten:
6.2. Praktische Übung
Wir schlagen vor, die NetBeans-Spring/Hibernate-Anwendung auf eine OpenEJB/EclipseLink-Architektur zu migrieren.
Die aktuelle Implementierung mit Spring / Hibernate
![]() |
Die zu erstellende Implementierung mit OpenEJB / EclipseLink
![]() |
6.2.1. Einrichten der Datenbank [ dbpam_eclipselink]
Falls sie noch nicht existiert, erstellen Sie die MySQL-Datenbank [dbpam_eclipselink]. Falls sie bereits existiert, löschen Sie alle darin enthaltenen Tabellen. Erstellen Sie eine NetBeans-Verbindung zu dieser Datenbank, wie in Abschnitt 6.2.1 beschrieben.
6.2.2. Erstkonfiguration des NetBeans-Projekts
- Laden Sie das Maven-Projekt [mv-pam-spring-hibernate]
- Erstellen Sie ein neues Maven-Java-Projekt [mv-pam-openejb-eclipselink] [1]
![]() |
- Erstellen Sie auf der Registerkarte [Dateien] [2] einen Ordner [conf] [3] unter dem Projektstammverzeichnis
- Legen Sie die folgende Datei [openejb.conf] [4] in diesem Ordner ab:
![]() |
- Erstellen Sie den Ordner [src/main/resources/META-INF] [5]
- Legen Sie darin die folgende Datei [persistence.xml] [6] ab:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="dbpam_eclipselinkPU" transaction-type="JTA">
<!-- the supplier JPA is EclipseLink -->
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- jpa entities -->
<class>jpa.Cotisation</class>
<class>jpa.Employe</class>
<class>jpa.Indemnite</class>
<!-- properties provider EclipseLink -->
<properties>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
- Zeile 12: Wir fordern detaillierte Protokolle von EclipseLink an,
- Zeile 13: Tabellen werden bei der Instanziierung der JPA-Schicht erstellt,
- Fügen Sie die OpenEJB- und EclipseLink-Bibliotheken sowie den MySQL-JDBC-Treiber zur [pom.xml]-Datei des Projekts hinzu:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st</groupId>
<artifactId>mv-pam-openejb-eclipselink</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mv-pam-openejb-eclipselink</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.swinglabs</groupId>
<artifactId>swing-layout</artifactId>
<version>1.0.3</version>
</dependency>
</dependencies>
<repositories>
<repository>
<url>http://download.eclipse.org/rt/eclipselink/maven.repo/</url>
<id>eclipselink</id>
<layout>default</layout>
<name>Repository for library Library[eclipselink]</name>
</repository>
</repositories>
</project>
- Zeilen 18–22: die OpenEJB-Abhängigkeit,
- Zeilen 30–39: die EclipseLink-Abhängigkeiten,
- Zeilen 41–44: die Abhängigkeit vom MySQL-JDBC-Treiber
6.2.3. Portierung der [DAO]-Schicht
Wir werden die [DAO]-Schicht portieren, indem wir Pakete aus dem Projekt [mv-pam-spring-hibernate] in das Projekt [mv-pam-openejb-eclipselink] kopieren.
- Kopieren Sie die Pakete [dao, exception, jpa]
![]() |
Die oben gemeldeten Fehler sind darauf zurückzuführen, dass die kopierte [DAO]-Schicht Spring verwendet und die Spring-Bibliotheken nicht mehr Teil des Projekts sind.
6.2.3.1. Die EJB [CotisationDao]
Wir erstellen die lokalen und Remote-Schnittstellen für das zukünftige EJB [CotisationDao]:
Die lokale Schnittstelle ICotisationDaoLocal:
Um sicherzustellen, dass die Pakete korrekt importiert werden, klicken Sie mit der rechten Maustaste auf den Code und wählen Sie [Importe korrigieren].
Die Remote-Schnittstelle ICotisationDaoRemote:
Anschließend ändern wir die Klasse [CotisationDao], um sie in ein EJB umzuwandeln:
Der Import, den diese Klasse aus dem Spring-Framework vorgenommen hat, verschwindet. Führen Sie im Projekt einen [Clean and Build] durch:
![]() |
In [1] gibt es keine Fehler mehr in der Klasse [CotisationDao].
6.2.3.2. Die EJBs [EmployeDao] und [IndemniteDao]
Wir wiederholen denselben Vorgang für die anderen Elemente der [DAO]-Schicht:
- Schnittstellen IEmployeDaoLocal und IEmployeDaoRemote, abgeleitet von IEmployeDao
- EJB `EmployeDao`, das diese beiden Schnittstellen implementiert
- Schnittstellen IIndemniteDaoLocal und IIndemniteDaoRemote, abgeleitet von IIndemniteDao
- EJB IndemniteDao, das diese beiden Schnittstellen implementiert
Sobald dies erledigt ist, gibt es keine Fehler mehr im Projekt [2].
6.2.3.3. Die Klasse [PamException]
Die Klasse [PamException] bleibt unverändert, mit einer kleinen Änderung:
Zeile 5 wurde hinzugefügt. Um die richtigen Importe zu erhalten, klicken Sie auf [Importe korrigieren].
Um die Anmerkung in Zeile 5 zu verstehen, denken Sie daran, dass jede Methode in den EJBs unserer [DAO]-Schicht:
- innerhalb einer Transaktion ausgeführt wird, die vom EJB-Container gestartet und beendet wird
- eine [PamException] auslöst, sobald etwas schiefgeht
![]() |
Wenn die [Business]-Schicht eine Methode M der [DAO]-Schicht aufruft, wird dieser Aufruf vom EJB-Container abgefangen. Es ist, als gäbe es eine Zwischenklasse zwischen der [Business]-Schicht und der [DAO]-Schicht – hier [EJB-Proxy] genannt –, die alle Aufrufe an die [DAO]-Schicht abfängt. Wenn der Aufruf der Methode M der [DAO]-Schicht abgefangen wird, startet der EJB-Proxy eine Transaktion und übergibt dann die Kontrolle an die Methode M der [DAO]-Schicht, die dann innerhalb dieser Transaktion ausgeführt wird. Die Methode M kann mit oder ohne Ausnahme beendet werden.
- Wenn die Methode M ohne Ausnahme beendet wird, kehrt die Kontrolle zum EJB-Proxy zurück, der die Transaktion durch ein Commit beendet. Die Kontrolle wird dann an die aufrufende Methode in der [Business]-Schicht zurückgegeben
- Wenn die Methode M mit einer Ausnahme beendet wird, kehrt die Ausführung zum EJB-Proxy zurück, der die Transaktion durch einen Rollback beendet. Zusätzlich verpackt er diese Ausnahme in eine EJBException. Die Ausführung kehrt dann zur aufrufenden Methode in der [Business]-Schicht zurück, die somit eine EJBException erhält. Die Annotation in Zeile 5 oben verhindert diese Kapselung. Die [Business]-Schicht erhält daher eine PamException. Darüber hinaus weist das Attribut rollback=true den EJB-Proxy an, dass er bei Erhalt einer PamException die Transaktion zurückrollen muss.
6.2.3.4. Testen der [DAO]-Schicht
Unsere durch EJBs implementierte [DAO]-Schicht kann getestet werden. Wir beginnen damit, das [dao]-Paket aus [Test Packages] im Projekt [mv-pam-springhibernate] in das aktuell in Entwicklung befindliche Projekt zu kopieren [1]:
![]() |
Wir behalten nur den Test [JUnitInitDB] bei, der die Datenbank mit einigen Daten initialisiert [2]. Wir benennen die Klasse [JUnitInitDbLocal] um [3]. Die Klasse [JUnitInitDBLocal] wird die lokale Schnittstelle der EJBs der [DAO]-Schicht verwenden.
Zunächst ändern wir die Klasse [JUnitInitDBLocal] wie folgt:
- Zeilen 3–5: Verweise auf die lokalen Schnittstellen der EJBs in der [DAO]-Schicht
- Zeile 7: @BeforeClass kennzeichnet die Methode, die beim Start des JUnit-Tests ausgeführt wird
- Zeilen 10–13: Initialisierung des OpenEJB-Containers. Diese Initialisierung ist proprietär und variiert je nach EJB-Container.
- Zeile 13: Wir verfügen über einen JNDI-Kontext (Java Naming and Directory Interface), der den Zugriff auf EJBs über Namen ermöglicht. Bei OpenEJB wird die lokale Schnittstelle eines EJBs durch ELocal und die Remote-Schnittstelle durch ERemote bezeichnet.
- Zeilen 15–17: Wir fordern eine Referenz auf die lokalen Schnittstellen der EJBs [EmployeDao, CotisationDao, IndemniteDao] aus dem JNDI-Kontext an.
![]() |
Erstellen Sie das Projekt, starten Sie gegebenenfalls den MySQL-Server und führen Sie den Test JUnitInitDBLocal aus. Beachten Sie, dass die Datei [persistence.xml] so konfiguriert wurde, dass die Tabellen bei jedem Durchlauf neu erstellt werden. Vor dem Ausführen des Tests sollten Sie alle Tabellen in der MySQL-Datenbank [dbpam_eclipselink] löschen.
![]() |
- Löschen Sie in [1] auf der Registerkarte [Services] die Tabellen aus der in Abschnitt 6.2.1 eingerichteten NetBeans-Verbindung.
- In [2] enthält die Datenbank [dbpam_eclipselink] keine Tabellen mehr
- In [3] wird das Projekt erstellt
- In [4] wird der Test „JUnitInitDBLocal“ ausgeführt
![]() |
- In [5] wurde der Test bestanden
- In [6] aktualisieren Sie die NetBeans-Verbindung
- In [7] sehen wir die 4 Tabellen, die von der JPA-Schicht erstellt wurden. Der Zweck des Tests bestand darin, diese zu füllen. Wir sehen uns den Inhalt einer davon an
![]() |
- in [8] den Inhalt der Tabelle [EMPLOYEES]
Der OpenEJB-Container zeigte Protokolle in der Konsole an:
- Zeilen 2–3: die beiden JNDI-Namen des EJB [CotisationDaoLocal],
- Zeilen 4–5: die beiden JNDI-Namen des EJB [CotisationDaoRemote],
- Zeilen 7–8: die beiden JNDI-Namen des EJB [EmployeDaoLocal],
- Zeilen 9–10: die beiden JNDI-Namen des EJB [EmployeDaoRemote],
- Zeilen 12–13: die beiden JNDI-Namen des EJB [IndemniteDaoLocal],
- Zeilen 14–15: die beiden JNDI-Namen des EJB [EmployeeDaoRemote].
Wir führen denselben Test erneut durch, diesmal unter Verwendung der Remote-Schnittstelle der EJBs.
![]() |
In [1] wurde die Klasse [JUnitInitDBLocal] kopiert und in [JUnitInitDBRemote] eingefügt. In dieser Klasse ersetzen wir die lokalen Schnittstellen durch die Remote-Schnittstellen:
Sobald dies erledigt ist, kann die neue Testklasse ausgeführt werden. Löschen Sie zuvor über die NetBeans-Verbindung [dbpam_eclipselink] die Tabellen aus der Datenbank [dbpam_eclipselink].
![]() |
Überprüfen Sie mithilfe der NetBeans-Verbindung [dbpam_eclipselink], ob die Datenbank gefüllt wurde.
6.2.4. Portierung der [Business]-Schicht
Wir werden die [Business]-Schicht portieren, indem wir Pakete aus dem Projekt [mv-pam-spring-hibernate] in das Projekt [mv-pam-openejb-eclipselink] kopieren.
![]() |
Die oben [1] gemeldeten Fehler sind darauf zurückzuführen, dass die kopierte [Business]-Schicht Spring verwendet und die Spring-Bibliotheken nicht mehr Teil des Projekts sind.
6.2.4.1. Die [Business]-EJB
Wir gehen genauso vor wie beim [CotisationDao]-EJB beschrieben. Zunächst erstellen wir in [2] die lokalen und Remote-Schnittstellen für das zukünftige [Metier]-EJB. Beide leiten sich von der ursprünglichen [IMetier]-Schnittstelle ab.
Sobald dies erledigt ist, ändern wir in [3] die Klasse [Business] so, dass sie zu einem EJB wird:
- Zeile 1: Die Annotation @Stateless macht die Klasse zu einem EJB
- Zeile 2: Jede Methode der Klasse wird innerhalb einer Transaktion ausgeführt
- Zeile 3: Die [Metier]-EJB implementiert sowohl die lokale als auch die Remote-Schnittstelle, die wir gerade definiert haben
- Zeile 7: Die [Metier]-EJB nutzt die [CotisationDao]-EJB über deren lokale Schnittstelle. Das bedeutet, dass die [Business]- und die [DAO]-Schicht in derselben JVM laufen müssen.
- Zeile 6: Die Annotation @EJB stellt sicher, dass der EJB-Container die Referenz auf die lokale Schnittstelle des [CotisationDao]-EJBs selbst einfügt. Der andere Ansatz, auf den wir gestoßen sind, ist die Verwendung eines JNDI-Kontexts.
- Zeilen 8–11: Der gleiche Mechanismus wird für die beiden anderen EJBs in der [DAO]-Schicht verwendet.
6.2.4.2. Testen der [Business]-Schicht
Unsere [business]-Schicht, die durch ein EJB implementiert wird, kann getestet werden. Wir beginnen damit, das [business]-Paket aus [Test Packages] im Projekt [mv-pam-spring-hibernate] in das derzeit im Aufbau befindliche Projekt [1] zu kopieren:
![]() |
- in [1], das Ergebnis des Kopiervorgangs
- in [2] löschen wir den ersten Test
- in [3] wird der verbleibende Test in [JUnitMetierLocal] umbenannt
Die Klasse [JUnitMetierLocal] sieht nun wie folgt aus:
- Zeile 4: Verweis auf die lokale Schnittstelle des EJB [Metier]
- Zeilen 8–12: OpenEJB-Container-Konfiguration identisch mit der im [DAO]-Schicht-Test verwendeten
- Zeilen 15–19: Wir fordern in Zeile 12 Referenzen aus dem JNDI-Kontext auf die drei EJBs in der [DAO]-Schicht und auf die EJB in der [Business]-Schicht an. Die EJBs in der [DAO]-Schicht werden zur Initialisierung der Datenbank verwendet, und die EJB in der [Business]-Schicht wird zur Durchführung von Tests zur Gehaltsberechnung verwendet.
Die Ausführung des [JUnitMetierLocal]-Tests liefert das folgende Ergebnis [1]:
![]() |
In [2] duplizieren wir [JUnitMetierLocal] als [JUnitMetierRemote], um diesmal die Remote-Schnittstelle des [Metier]-EJB zu testen. Der Code für [JUnitMetierRemote] wird so geändert, dass diese Remote-Schnittstelle verwendet wird. Der Rest bleibt unverändert.
- Zeilen 4 und 19: Wir verwenden die Remote-Schnittstelle des [Business]-EJB.
- Zeilen 15–17: Wir verwenden die Remote-Schnittstellen der [DAO]-Schicht
- Zeilen 34–35: Da bei Remote-Schnittstellen Objekte, die zwischen Client und Server ausgetauscht werden, als Wert übergeben werden, müssen wir das von der Methode create(Indemnite i) zurückgegebene Ergebnis abrufen. Bei lokalen Schnittstellen, bei denen Objekte als Referenz übergeben werden, war dies nicht erforderlich.
Sobald dies erledigt ist, kann das Projekt kompiliert und der [JUnitMetierRemote]-Test ausgeführt werden:
![]() |
6.2.5. Portierung der [Konsolen]-Ebene
Wir werden die [console]-Schicht portieren, indem wir Pakete aus dem Projekt [mv-pam-spring-hibernate] in das Projekt [mv-pam-openejb-eclipselink] kopieren.
![]() |
Die oben [1] gemeldeten Fehler sind darauf zurückzuführen, dass die kopierte [business]-Schicht Spring verwendet und die Spring-Bibliotheken nicht mehr Teil des Projekts sind. In [2] wird die Klasse [Main] in [MainLocal] umbenannt. Sie wird die lokale Schnittstelle des [Business]-EJB verwenden.
Der Code für die [MainLocal]-Klasse ändert sich wie folgt:
Die Änderungen befinden sich in den Zeilen 13–25. Auf diese Weise erhalten wir eine Referenz auf die [business]-Schicht, die sich geändert hat (Zeilen 17–22). Wir werden den neuen Code nicht erläutern, da er bereits in früheren Beispielen behandelt wurde. Sobald diese Änderungen vorgenommen wurden, weist das Projekt keine Fehler mehr auf (siehe [3]).
Wir konfigurieren das Projekt so, dass es mit Argumenten ausgeführt wird [1]:
![]() |
Damit die Konsolenanwendung normal läuft, müssen Daten in der Datenbank vorhanden sein. Dazu müssen Sie die Datei [META-INF/persistence.xml] ändern:
Zeile 14, die dazu führte, dass die Datenbanktabellen bei jedem Durchlauf neu erstellt wurden, ist auskommentiert. Das Projekt muss neu erstellt werden (Clean und Build), damit diese Änderung wirksam wird. Sobald dies geschehen ist, kann das Programm ausgeführt werden. Wenn alles gut geht, sieht die Konsolenausgabe in etwa wie folgt aus:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="dbpam_eclipselinkPU" transaction-type="JTA">
<!-- the supplier JPA is EclipseLink -->
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- jpa entities -->
<class>jpa.Cotisation</class>
<class>jpa.Employe</class>
<class>jpa.Indemnite</class>
<!-- properties provider EclipseLink -->
<properties>
<property name="eclipselink.logging.level" value="FINE"/>
<!--
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
-->
</properties>
</persistence-unit>
</persistence>
Hier haben wir die lokale Schnittstelle der [Business]-Schicht verwendet. In einer zweiten Konsolenklasse verwenden wir nun deren Remote-Schnittstelle:
![]() |
In [1] wurde die Klasse [MainLocal] in [MainRemote] dupliziert. Der Code in [MainRemote] wurde so geändert, dass er die Remote-Schnittstelle der [business]-Schicht verwendet:
Es wurden Änderungen an den Zeilen 2 und 8 vorgenommen. Das Projekt ist so konfiguriert [2], dass die Klasse [MainRemote] ausgeführt wird. Die Ausführung liefert die gleichen Ergebnisse wie zuvor.
6.3. Fazit
Wir haben gezeigt, wie eine Spring/Hibernate-Architektur auf eine OpenEJB/EclipseLink-Architektur migriert wird.
Die Spring/Hibernate-Architektur
![]() |
Die OpenEJB/EclipseLink-Architektur
![]() |
Der Portierungsprozess verlief reibungslos, da die ursprüngliche Anwendung in Schichten strukturiert war. Dieser Punkt ist wichtig zu verstehen.




























