6. Version 2: Architektur OpenEJB / JPA
6.1. Einführung in die Grundsätze der Portierung
Hier stellen wir die Grundsätze vor, die für die Portierung einer JPA-/Spring-/Hibernate-Anwendung auf eine JPA-/OpenEJB-/EclipseLink-Anwendung gelten. Die Erstellung der Maven-Projekte erfolgt erst in Abschnitt 6.2.
6.1.1. Die beiden Architekturen
Die aktuelle Implementierung mit Spring / Hibernate
![]() |
Die zu erstellende Implementierung mit OpenEJB / EclipseLink
![]() |
6.1.2. Die Bibliotheken der Projekte
- Die Schichten [DAO] und [metier] werden nicht mehr von Spring instanziiert. Sie werden stattdessen vom Container OpenEJB instanziiert.
- Die Bibliotheken des Spring-Containers und dessen Konfiguration werden durch die Bibliotheken des OpenEJB-Containers und dessen Konfiguration ersetzt.
- Die Bibliotheken der Schicht JPA / Hibernate werden durch die der Schicht JPA / EclipseLink ersetzt.
6.1.3. Konfiguration der Schicht JPA / EclipseLink / OpenEJB
- Die Datei [META-INF/persistence.xml], die die Schicht JPA konfiguriert, sieht nun wie folgt aus:
- Zeile 3: Die Transaktionen in einem Container EJB sind vom Typ JTA (Java-Transaktion API). Mit Spring waren sie vom Typ RESOURCE_LOCAL.
- Zeile 9: Die verwendete Implementierung JPA ist EclipseLink
- Zeilen 5–7: Die von der Schicht JPA verwalteten Entitäten
- Zeilen 11–13: Eigenschaften des Providers EclipseLink
- Zeile 12: Bei jeder Ausführung werden die Tabellen angelegt
Die Merkmale JDBC der Datenquelle JTA, die vom Container OpenEJB verwendet wird, werden durch die folgende Konfigurationsdatei [conf/openejb.conf] festgelegt:
- Zeile 3: Bei der Arbeit mit einem in die Anwendung selbst eingebetteten (embedded) Container OpenEJB wird die ID „Default JDBC Database“ verwendet.
- Zeile 5: Wir verwenden eine Datenbank MySQL [dbpam_eclipselink]
6.1.4. Implementierung der Schicht [DAO] durch EJB
- Die Klassen, die die Schicht [DAO] implementieren, werden zu EJB. Nehmen wir als Beispiel die Klasse [CotisationDao]:
Die Schnittstelle [ICotisationDao] in der Spring-Version sah wie folgt aus:
EJB wird dieselbe Schnittstelle in zwei verschiedenen Formen implementieren: einer lokalen und einer entfernten. Die lokale Schnittstelle kann von einem Client genutzt werden, der in derselben Instanz JVM ausgeführt wird, die entfernte Schnittstelle von einem Client, der in einer anderen Instanz JVM ausgeführt wird.
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 die Schnittstelle EJB, die sie implementieren wird.
Die entfernte 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 sie zu einer Remote-Schnittstelle für die Schnittstelle EJB, die sie implementieren wird.
Die Schicht [DAO] wird durch eine Klasse EJB implementiert, die 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 dafür sorgt, dass jede Methode der Klasse innerhalb einer Transaktion ausgeführt wird.
- Zeile 5: Die Annotation @PersistenceContext, die in die Klasse [CotisationDao] das EntityManager aus der Schicht JPA einfügt. Sie ist identisch mit der in der Spring-Version verwendeten.
Wenn die lokale Schnittstelle der Schicht [DAO] verwendet wird, wird der Client dieser Schnittstelle in derselben JVM ausgeführt.
![]() |
In dem oben dargestellten Beispiel tauschen die Schichten [metier] und [DAO] Objekte per Referenz aus. Wenn eine Schicht das gemeinsam genutzte Objekt ändert, erkennt die andere Schicht diese Änderung.
Wenn die Remote-Schnittstelle der Schicht [DAO] verwendet wird, läuft der Client dieser Schnittstelle in der Regel in einer anderen JVM.
![]() |
Im obigen Beispiel tauschen die Schichten [metier] und [DAO] Objekte per Wert aus (Serialisierung des ausgetauschten Objekts). Wenn eine Schicht ein gemeinsam genutztes Objekt ändert, erkennt die andere Schicht diese Änderung nur, wenn ihr das geänderte Objekt zurückgesendet wird.
6.1.5. Implementierung der Schicht [metier] durch eine EJB
- Die Klasse, die die Schicht [metier] implementiert, wird ebenfalls zu einem EJB, der eine lokale und eine entfernte Schnittstelle implementiert. Die ursprüngliche Schnittstelle [IMetier] sah wie folgt aus:
Aus der vorherigen Schnittstelle werden eine lokale und eine Remote-Schnittstelle erstellt:
Die Schnittstelle EJB der Schicht [metier] implementiert diese beiden Schnittstellen:
- Zeilen 1–2: Definieren ein EJB, bei dem jede Methode in einer Transaktion ausgeführt wird.
- Zeile 7: Eine Referenz auf die lokale Schnittstelle von EJB [CotisationDao].
- Zeile 6: Die Annotation @EJB weist den Container EJB an, eine Referenz auf die lokale Schnittstelle von EJB [CotisationDao] einzufügen.
- Zeilen 8–11: Das Gleiche wird für die lokalen Schnittstellen von EJB, [EmployeDao] und [IndemniteDao] wiederholt.
Wenn schließlich die Instanzen EJB und [Metier] instanziiert werden, werden die Felder in den Zeilen 7, 9 und 11 mit Verweisen auf die lokalen Schnittstellen der drei EJB der Schicht [DAO] initialisiert. Man geht hier also davon aus, dass die Schichten [metier] und [DAO] in derselben JVM ausgeführt werden.
![]() |
6.1.6. Die Clients von EJB
![]() |
In dem obigen Schema muss die Schicht [ui], um mit der Schicht [metier] zu kommunizieren, eine Referenz auf die Remote-Schnittstelle der Schicht EJB von der Schicht [metier] abrufen.
![]() |
Im obigen Schema muss die Schicht [ui], um mit der Schicht [metier] zu kommunizieren, eine Referenz auf die lokale Schnittstelle der Schicht EJB der Schicht [metier] abrufen. Die Vorgehensweise zum Abrufen dieser Referenzen unterscheidet sich von Container zu Container. Für den Container OpenEJB kann wie folgt vorgegangen werden:
Referenz auf der lokalen Schnittstelle:
- Zeilen 2–5: Der Container OpenEJB wird initialisiert.
- Zeile 5: Es liegt ein JNDI-Kontext (Java Naming and Directory Interface) vor, über den Referenzen auf die EJB abgerufen werden können. Jeder EJB wird durch einen Namen JNDI bezeichnet:
- (Fortsetzung)
- Für die lokale Schnittstelle wird dem Namen des EJB „Local“ hinzugefügt (Zeilen 7–9)
- Für die Remote-Schnittstelle wird „Remote“ an den Namen des EJB angehängt
Bei Java EE 5 ändern sich diese Regeln je nach Container EJB. Das stellt eine Schwierigkeit dar. Mit Java EE 6 wurde eine auf allen Anwendungsservern portierbare Notation JNDI eingeführt.
Der vorstehende Code ruft Referenzen auf die lokalen Schnittstellen der EJB über deren Namen JNDI ab. Wir haben zuvor erwähnt, dass diese auch über die Annotation @EJB abgerufen werden können. Man könnte daher Folgendes schreiben:
Die Annotation @EJB wird nur berücksichtigt, wenn sie zu einer Klasse gehört, die vom Container EJB geladen wird. Dies ist beispielsweise bei der Klasse [Metier] der Fall. Der obige Code gehört hingegen zu einer Konsolenklasse, die nicht vom Container EJB geladen wird. Daher muss man die Namen JNDI oder EJB verwenden.
Nachfolgend der Code, um eine Referenz auf die Remote-Schnittstelle von EJB und [Metier] zu erhalten:
6.2. Praktische Übung
Es ist geplant, die NetBeans-Anwendung mit Spring und Hibernate auf eine Architektur mit OpenEJB und EclipseLink zu portieren.
Die aktuelle Implementierung mit Spring / Hibernate
![]() |
Die zu erstellende Implementierung mit OpenEJB / EclipseLink
![]() |
6.2.1. Einrichtung der Datenbank [dbpam_eclipselink]
Falls die Datenbank noch nicht vorhanden ist, erstellen Sie die Datenbank MySQL [dbpam_eclipselink]. Falls sie bereits vorhanden ist, löschen Sie alle darin enthaltenen Tabellen. Richten Sie eine NetBeans-Verbindung zu dieser Datenbank ein, 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 mit den Namen [mv-pam-openejb-eclipselink] und [1]
![]() |
- Erstellen Sie auf der Registerkarte „[Files] [2]“ einen Ordner „[conf] [3]“ im Stammverzeichnis des Projekts
- in diesem Ordner die folgende Datei [openejb.conf] [4] ablegen:
![]() |
- Erstellen Sie den Ordner [src / main/ resources/ META-INF] [5]
- die folgenden Dateien darin ablegen: [persistence.xml] [6]
<?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">
<!-- Der Anbieter JPA ist EclipseLink -->
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- Jpa-Entitäten -->
<class>jpa.Cotisation</class>
<class>jpa.Employe</class>
<class>jpa.Indemnite</class>
<!-- Eigenschaften des Anbieters 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: Es werden detaillierte Protokolle für EclipseLink angefordert,
- Zeile 13: Die Tabellen werden bei der Instanziierung der Schicht JPA angelegt,
- Fügen Sie die Bibliotheken OpenEJB, EclipseLink sowie den Treiber JDBC von MySQL zur Datei [pom.xml] 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 Abhängigkeit OpenEJB,
- Zeilen 30–39: die Abhängigkeiten EclipseLink,
- Zeilen 41–44: die Abhängigkeit des Treibers JDBC von MySQL
6.2.3. Portierung der Schicht [DAO]
Wir werden die Portierung der Schicht [DAO] durchführen, indem wir Pakete aus dem Projekt [mv-pam-spring-hibernate] in das Projekt [mv-pam-openejb-eclipselink] kopieren.
- Pakete kopieren: [dao, exception, jpa]
![]() |
Die oben gemeldeten Fehler sind darauf zurückzuführen, dass die kopierte Schicht [DAO] Spring verwendet und die Spring-Bibliotheken nicht mehr Teil des Projekts sind.
6.2.3.1. EJB [CotisationDao]
Wir erstellen die lokale und die Remote-Schnittstelle des zukünftigen EJB [CotisationDao]:
Die lokale Schnittstelle ICotisationDaoLocal:
Um die richtigen import-Pakete zu erhalten, führen Sie [clic droit sur le code / Fix Imports] aus.
Die Remote-Schnittstelle ICotisationDaoRemote:
Anschließend ändern wir die Klasse [CotisationDao] in EJB:
Die Schnittstelle import, die diese Klasse im Spring-Framework bereitstellte, verschwindet. Erstellen Sie eine Schnittstelle [Clean and Build] für das Projekt:
![]() |
In [1] gibt es keine Fehler mehr bei der Klasse [CotisationDao].
6.2.3.2. Die EJB, [EmployeDao] und [IndemniteDao]
Der gleiche Vorgang wird für die anderen Elemente der Ebene [DAO] wiederholt:
- die von IEmployeDao abgeleiteten Schnittstellen IEmployeDaoLocal und IEmployeDaoRemote
- EJB und EmployeDao, die diese beiden Schnittstellen implementieren
- Schnittstellen IIndemniteDaoLocal, IIndemniteDaoRemote, abgeleitet von IIndemniteDao
- EJB und IndemniteDao, die diese beiden Schnittstellen implementieren
Nachdem dies erledigt ist, gibt es keine Fehler mehr im Projekt [2].
6.2.3.3. Die Klasse [PamException]
Die Klasse [PamException] bleibt bis auf eine Kleinigkeit unverändert:
Zeile 5 wurde hinzugefügt. Um die richtigen import zu erhalten, muss man [Fix imports] verwenden.
Um die Anmerkung in Zeile 5 zu verstehen, muss man bedenken, dass jede Methode der EJB unserer Schicht [DAO]:
- in einer Transaktion ausgeführt wird, die vom Container EJB gestartet und beendet wird
- eine Ausnahme vom Typ [PamException] auslöst, sobald etwas schiefgeht
![]() |
Wenn die Schicht [metier] eine Methode M der Schicht [DAO] aufruft, wird dieser Aufruf vom Container EJB abgefangen. Es ist so, als gäbe es eine Zwischenklasse zwischen der Schicht [metier] und der Schicht [DAO], die hier [Proxy EJB] heißt und alle Aufrufe an die Schicht [DAO] abfängt. Wenn der Aufruf der Methode M der Schicht [DAO] abgefangen wird, startet der Proxy EJB eine Transaktion und übergibt dann die Kontrolle an die Methode M der Schicht [DAO], die daraufhin innerhalb dieser Transaktion ausgeführt wird. Die Methode M endet mit oder ohne Ausnahme.
- Wenn die Methode M ohne Ausnahme endet, kehrt die Ausführung zum Proxy EJB zurück, der die Transaktion durch Validierung mittels eines commit abschließt. Der Ausführungsfluss wird anschließend an die aufrufende Methode der Schicht [metier] zurückgegeben.
- Wenn die Methode M mit einer Ausnahme endet, kehrt die Ausführung zum Proxy EJB zurück, der die Transaktion durch einen rollback als ungültig markiert und damit abschließt. Außerdem kapselt er diese Ausnahme in einen Typ EJBException ein. Der Ausführungsfluss wird anschließend an die aufrufende Methode der Schicht [metier] zurückgegeben, die somit ein EJBException erhält. Die Anmerkung in Zeile 5 oben verhindert diese Kapselung. Die Schicht [metier] erhält somit ein PamException. Zudem weist das Attribut rollback=true den Proxy EJB an, die Transaktion zu verwerfen, sobald er ein PamException erhält.
6.2.3.4. Test der Schicht [DAO]
Unsere durch EJB implementierte Schicht [DAO] kann getestet werden. Zunächst kopieren wir das Paket [dao] aus [Test Packages] des Projekts [mv-pam-springhibernate] in das derzeit im Aufbau befindliche Projekt [1]:
![]() |
Wir behalten nur den Test [JUnitInitDB] bei, der die Datenbank mit einigen Daten aus [2] initialisiert. Wir benennen die Klasse [ JUnitInitDbLocal] in [3] um. Die Klasse [JUnitInitDBLocal] wird die lokale Schnittstelle der Klasse EJB aus der Schicht [DAO] verwenden.
Zunächst ändern wir die Klasse [JUnitInitDBLocal] wie folgt:
- Zeilen 3–5: Verweise auf die lokalen Schnittstellen von EJB der Schicht [DAO]
- Zeile 7: @BeforeClass kennzeichnet die Methode, die beim Start des Tests JUnit ausgeführt wird
- Zeilen 10–13: Initialisierung des Containers OpenEJB. Diese Initialisierung ist proprietär und ändert sich mit jedem Container EJB.
- Zeile 13: Es liegt ein JNDI-Kontext (Java Naming and Directory Interface) vor, der den Zugriff auf die EJB über Namen ermöglicht. Bei OpenEJB wird die lokale Schnittstelle eines EJB E als ELocal und die entfernte Schnittstelle als ERemote bezeichnet.
- Zeilen 15–17: Vom Kontext JNDI wird eine Referenz auf die lokalen Schnittstellen der EJB und [EmployeDao, CotisationDao, IndemniteDao] angefordert.
![]() |
Das Projekt wird erstellt (Build), der Server MySQL wird bei Bedarf gestartet, und der Test JUnitInitDBLocal wird ausgeführt. Es sei daran erinnert, dass die Datei [persistence.xml] so konfiguriert wurde, dass die Tabellen bei jeder Ausführung neu erstellt werden. Vor der Ausführung des Tests sollten eventuelle Tabellen aus den Datenbanken MySQL und [dbpam_eclipselink] gelöscht werden.
![]() |
- in [1], auf der Registerkarte [Services], werden die Tabellen der in Abschnitt 6.2.1 hergestellten NetBeans-Verbindung gelöscht.
- 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] war der Test erfolgreich
- in [6] wird die NetBeans-Verbindung aktualisiert
- in [7], man sieht die 4 von der Schicht JPA erstellten Tabellen. Ziel des Tests war es, diese zu füllen. Man zeigt den Inhalt einer davon an
![]() |
- in [8], der Inhalt der Tabelle [EMPLOYES]
Der Container OpenEJB hat Protokolleinträge in der Konsole angezeigt:
- Zeilen 2–3: die beiden Namen JNDI von EJB und [CotisationDaoLocal],
- Zeilen 4–5: die beiden Namen JNDI von EJB und [CotisationDaoRemote],
- Zeilen 7–8: die beiden Namen JNDI aus EJB und [EmployeDaoLocal],
- Zeilen 9–10: die beiden Namen JNDI aus EJB und [EmployeDaoRemote],
- Zeilen 12–13: die beiden Namen JNDI aus EJB und [IndemniteDaoLocal],
- Zeilen 14–15: die beiden Namen JNDI aus den Namen EJB und [EmployeDaoRemote].
Wir führen denselben Test erneut durch, diesmal unter Verwendung der Remote-Schnittstelle von EJB.
![]() |
In [1] wurde die Klasse [JUnitInitDBLocal] in [JUnitInitDBRemote] kopiert (Kopieren/Einfügen). In dieser Klasse ersetzen wir die lokalen Schnittstellen durch die Remote-Schnittstellen:
Anschließend 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 mit der NetBeans-Verbindung [dbpam_eclipselink], ob die Datenbank gefüllt wurde.
6.2.4. Portierung der Schicht [metier]
Wir werden die Portierung der Ebene [metier] durchführen, indem wir Pakete aus dem Projekt [mv-pam-spring-hibernate] in das Projekt [mv-pam-openejb-eclipselink] kopieren.
![]() |
Die oben gemeldeten Fehler [1] sind darauf zurückzuführen, dass die kopierte Schicht [metier] Spring verwendet und die Spring-Bibliotheken nicht mehr Teil des Projekts sind.
6.2.4.1. EJB [Metier]
Wir gehen genauso vor wie bei den EJB und [CotisationDao] beschrieben. Zunächst erstellen wir in [2] die lokale und die Remote-Schnittstelle des zukünftigen EJB [Metier]. Beide leiten sich von der ursprünglichen Schnittstelle [IMetier] ab.
Anschließend ändern wir in [3] die Klasse [Metier] so, dass sie zu einer EJB wird:
- Zeile 1: Die Annotation @Stateless macht die Klasse zu einer EJB
- Zeile 2: Jede Methode der Klasse wird in einer Transaktion ausgeführt
- Zeile 3: Die Klasse EJB [Metier] implementiert die beiden Schnittstellen „local“ und „remote“, die wir gerade definiert haben
- Zeile 7: Die Klasse EJB [Metier] wird die Klasse EJB [CotisationDao] über deren lokale Schnittstelle nutzen. Das bedeutet, dass die Schichten [metier] und [DAO] in derselben JVM ausgeführt werden müssen.
- Zeile 6: Die Annotation @EJB sorgt dafür, dass der Container EJB die Referenz selbst in die lokale Schnittstelle von EJB [CotisationDao] einfügt. Die andere Methode, auf die wir gestoßen sind, ist die Verwendung eines JNDI-Kontexts.
- Zeilen 8–11: Für die beiden anderen EJB der Schicht [DAO] wird derselbe Mechanismus verwendet.
6.2.4.2. Test der Schicht [metier]
Unsere durch ein EJB implementierte Schicht [metier] kann getestet werden. Zunächst kopieren wir das Paket [metier] aus [Test Packages] des Projekts [mv-pam-spring-hibernate] in das aktuell im Aufbau befindliche Projekt [1]:
![]() |
- in [1], das Ergebnis des Kopiervorgangs
- in [2], der erste Test wird gelöscht
- in [3] wird der verbleibende Test in [JUnitMetierLocal] umbenannt
Die Klasse [JUnitMetierLocal] sieht nun wie folgt aus:
- Zeile 4: ein Verweis auf die lokale Schnittstelle von EJB [Metier]
- Zeilen 8–12: Konfiguration des Containers OpenEJB, identisch mit der im Test der Schicht [DAO] vorgenommenen
- Zeilen 15–19: Es werden die Referenzen des Kontexts JNDI aus Zeile 12 sowie Referenzen auf die drei EJB der Schicht [DAO] sowie auf das EJB der Schicht [metier] abzufragen. Die EJB der Ebene [DAO] dienen zur Initialisierung der Datenbank, die EJB der Ebene [metier] zur Durchführung von Tests zur Lohnabrechnung.
Die Ausführung des Tests [JUnitMetierLocal] liefert das folgende Ergebnis [1]:
![]() |
In [2] wird [JUnitMetierLocal] in [JUnitMetierRemote] dupliziert, um diesmal die Remote-Schnittstelle von EJB und [Metier] zu testen. Der Code von [JUnitMetierRemote] wird so geändert, dass diese Remote-Schnittstelle verwendet wird. Der Rest bleibt unverändert.
- Zeilen 4 und 19: Es wird die Remote-Schnittstelle von EJB und [Metier] verwendet.
- Zeilen 15–17: Es werden die Remote-Schnittstellen der Schicht [DAO] verwendet.
- Zeilen 34–35: Da bei Remote-Schnittstellen die zwischen Client und Server ausgetauschten Objekte wertweise übergeben werden, muss das von der Methode `create(Indemnite i)` zurückgegebene Ergebnis abgerufen werden. Bei lokalen Schnittstellen, bei denen Objekte per Referenz übergeben werden, war dies nicht erforderlich.
Anschließend kann das Projekt kompiliert und der Test [JUnitMetierRemote] ausgeführt werden:
![]() |
6.2.5. Portierung der Schicht [console]
Wir werden die Portierung der Schicht [console] vornehmen, indem wir Pakete aus dem Projekt [mv-pam-spring-hibernate] in das Projekt [mv-pam-openejb-eclipselink] kopieren.
![]() |
Die oben gemeldeten Fehler [1] sind darauf zurückzuführen, dass die kopierte Schicht [metier] 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 von EJB [Metier] verwenden.
Der Code der Klasse [MainLocal] entwickelt sich wie folgt:
Die Änderungen befinden sich in den Zeilen 13–25. Dabei ändert sich die Art und Weise, wie auf die Ebene [metier] verwiesen wird (Zeilen 17–22). Wir gehen nicht näher auf den neuen Code ein, da dieser bereits in früheren Beispielen behandelt wurde. Nach Durchführung dieser Änderungen weist das Projekt keine Fehler mehr auf (siehe [3]).
Wir konfigurieren das Projekt so, dass es mit den Argumenten [1] ausgeführt wird:
![]() |
Damit die Konsolenanwendung normal ausgeführt wird, müssen Daten in der Datenbank vorhanden sein. Dazu muss die Datei [META-INF/persistence.xml] geändert werden:
<?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">
<!-- Der Anbieter JPA ist EclipseLink -->
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- Jpa-Entitäten -->
<class>jpa.Cotisation</class>
<class>jpa.Employe</class>
<class>jpa.Indemnite</class>
<!-- Eigenschaften des Anbieters EclipseLink -->
<properties>
<property name="eclipselink.logging.level" value="FINE"/>
<!--
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
-->
</properties>
</persistence-unit>
</persistence>
Zeile 14, die dazu führte, dass die Datenbanktabellen bei jeder Ausführung neu angelegt wurden, wird auskommentiert. Das Projekt muss neu erstellt werden (Clean and Build), damit diese Änderung berücksichtigt wird. Anschließend kann das Programm ausgeführt werden. Wenn alles korrekt läuft, erscheint eine Konsolenausgabe ähnlich der folgenden:
Wir haben hier die lokale Schnittstelle der Schicht [metier] verwendet. Nun nutzen wir deren Remote-Schnittstelle in einer zweiten Konsolenklasse:
![]() |
In [1] wurde die Klasse [MainLocal] in [MainRemote] dupliziert. Der Code von [MainRemote] wurde geändert, um die Remote-Schnittstelle der Schicht [metier] zu verwenden:
Die Änderungen wurden in den Zeilen 2 und 8 vorgenommen. Das Projekt [2] wurde so konfiguriert, dass es die Klasse [MainRemote] ausführt. Die Ausführung liefert dieselben Ergebnisse wie zuvor.
6.3. Conclusion
Wir haben gezeigt, wie eine Spring-/Hibernate-Architektur auf eine OpenEJB-/EclipseLink-Architektur portiert werden kann.
Die Spring-/Hibernate-Architektur
![]() |
Die OpenEJB-/EclipseLink-Architektur
![]() |
Die Portierung konnte ohne größere Schwierigkeiten durchgeführt werden, da die ursprüngliche Anwendung schichtweise strukturiert war. Dieser Punkt ist wichtig zu verstehen.




























