Workshop - Java Persistence API

1 Vorüberlegung

Im Vorfeld muss man sich erst mal für ein paar Dinge entscheiden, bevor man überhaupt JPA nutzen kann.

Die Application Server und JPA Implementierungen werden von den IDE's nur halbherzig unterstützt. Meist gehts nichts auf Anhieb und man muss selbst Hand anlegen, um JPA in der IDE und dem Application Server nutzen zu können

Wer hier schon keinen Bock mehr hat, dem möchte ich NetBeans in der Version 8.0.2 ans Herz legen. Der Aufwand hält sich hier sehr in Grenzen!

2 Eclipse + EclipseLink + WildFly

Beginnen möchte ich mit der IDE Eclipse, der JPA Implementierung EclipseLink und dem Application Server WildFly

Ich gehe davon aus, dass ihr das JDK schon installiert habt!

2.1 WildFly

2.1.1 Installation

  1. Unter folgenden Link bitte die Version mit der Beschreibung Java EE7 Full & Web Distribution herunterladen

    http://wildfly.org/downloads/
  2. Die ZIP-Datei an einen Ort eurer Wahl entpacken.

2.1.2 Konfiguration

ExclipseLink hinzufügen

  1. Unter folgenden Link das ZIP-Paket EclipseLink Installer herunterladen:

    http://www.eclipse.org/eclipselink/#download
  2. Das ZIP entpacken und die Datei eclipselink.jar im Ordner jlib in folgendes Unterverzeichnis des WildFly-Verzeichnisses kopieren

    \modules\system\layers\base\org\eclipse\persistence\main
  3. Die Datei module.xml in obigen Unterverzechnis muss wie folgt modifiziert werden:

    <resources>
        <resource-root path="jipijapa-eclipselink-10.1.0.Final.jar"/>
        <resource-root path="eclipselink.jar">
            <filter>
                <exclude path="javax/**" />
            </filter>
        </resource-root>
    </resources>

Oracle DB Treiber hinzufügen

  1. Den Oracle Datenbanktreiber ojdbc7.jar unter folgendem Link herunterladen:

    http://www.oracle.com/technetwork/database/features/jdbc/default-2280470.html
  2. Wir kopieren die Datei ojdbc7.jar in das WildFly Verzeichnis unter:

    \modules\system\layers\base\com\oracle\main

    Sollte der Pfad teilweise nicht existieren, dann müssen die jeweiligen Unterverzeichnisse erzeugt werden!

  3. Jetzt legen wir eine neue Textdatei mit dem Namen module.xml an

    Mit einem Texteditor fügen wir folgendes ein:

    <module xmlns="urn:jboss:module:1.1" name="com.oracle">
        <resources>
          <resource-root path="ojdbc7.jar"/>
        </resources>
        <dependencies>
          <module name="javax.api"/>
          <module name="javax.transaction.api"/>
        </dependencies>
    </module>

Datasource anlegen

Dies könnten wir im Webinterface tun, aber die betreffende Datei zu verändern ist schneller erledigt!

  1. Hierzu müssen wir die Datei standalone.xml in folgendem Pfad mit einem Texteditor verändern:

    \standalone\configuration
  2. Hier suchen wir die Zeile:

    <subsystem xmlns="urn:jboss:domain:datasources:4.0">
  3. Anschließend ersetzen wir den bestehenden Teil ab dem Tag subsystem bis zum Ende Tag mit folgenden Zeilen

    Achtet auf user-name und password

    <subsystem xmlns="urn:jboss:domain:datasources:4.0">
        <datasources>
            <datasource jta="true" jndi-name="java:/OracleDS" pool-name="OracleDS" enabled="true" use-ccm="true">
                <connection-url>jdbc:oracle:thin:@localhost:1521:xe</connection-url>
                <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
                <driver>oracle</driver>
                <security>
                    <user-name>Projekt</user-name>
                    <password>cdt</password>
                </security>
                <validation>
                    <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker"/>
                    <background-validation>true</background-validation>
                    <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker"/>
                    <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/>
                </validation>
            </datasource>
            <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                <driver>h2</driver>
                <security>
                    <user-name>sa</user-name>
                    <password>sa</password>
                </security>
            </datasource>
            <drivers>
                <driver name="h2" module="com.h2database.h2">
                    <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                </driver>
                <driver name="oracle" module="com.oracle">
                    <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
                </driver>
            </drivers>
        </datasources>
    </subsystem>

Damit ist WildFly fertig konfiguriert!

2.2 Eclipse

2.2.1 Installation

  1. Download der IDE Eclipse
  2. Ausführen des Installationsprogrammes
  3. Anschließend erscheint eine Auswahlmöglichkeit, die Anpassungen für verschiedene Programmierzwecke bietet.

    Hier wählen wir Eclipse IDE for Java EE Developers aus

  4. Anschließend wählt man Installationspfad und 32/64 bit Version aus und klickt auf Install

2.2.2 Konfiguration

Eclipse starten und die Java EE Perspektive aktivieren falls noch nicht geschehen:

Menü Window Perspective Open Perspective other

DataSource anlegen

Ja richtig gelesen. Die IDE muss auch wissen wo die DB liegt!

  1. Menü Window Data Source Explorer

    Im unteren Teil der IDE erscheint danach ein kleines Bäumchen mit dem Zweig Database Connections

  2. Macht einen Rechtsklick auf Database Connections und wählt New...
  3. Ein Fenster erscheint in dem ihr unter Connection Profile Types eine Datenbank auswählt. In meinem Fall Oracle

    Vergebt bitte eine aussagekräftigen Namen und klickt auf Next

  4. Nun fügen wir den Treiber hinzu. Klickt hierzu auf das Symbol auf welches der rote Pfeil im Bild zeigt

  5. Wählt aus der Liste irgendeinen Eintrag mit Oracle Thin Driver aus und klickt auf das Tab JAR List

  6. Wählt den Eintrag aus und klickt auf Edit JAR/Zip...

    Anschließend wählt ihr den Treiber ojdbc6.jar oder ojdbc7.jar aus und klickt auf Öffnen

    Danach sieht es wie folgt aus:

    Nun bitte das Tab Properties auswählen

  7. Handelt es sich um eine Oracle Express 11g Standardinstallation muss Catalog , Connection URL , Database Name und Driver Class auf die Werte im Screenshot geändert werden

    User und Password natürlich eure Daten

  8. Danach auf OK und im vorhergehenden Fenster auf Finish klicken

Application Server anlegen

Menü Window Show View Servers

Im sich öffnenden Bereich an einer freien Stelle einen Rechtsklick machen und im Kontextmenü New... Server auswählen auswählen

  1. Im Ordner Red Hat JBoss Middleware den Eintrag JBoss As, WildFly & EAP Server Tools auswählen und auf Next klicken

    Das herunterladen der Repositories könnte etwas dauern

  2. Im Verlauf muss man die Lizenz akzeptieren und auf Finish klicken

  3. Auch ein Sicherheitshinweis kann kommen, Hier auf OK klicken

  4. Anschließend wird ein Neustart fällig

  5. Nach dem Neustart:

    Menü Window Show View Servers

    Im sich öffnenden Bereich an einer freien Stelle einen Rechtsklick machen und im Kontextmenü New... Server auswählen auswählen

  6. Im Ordner JBoss Community den aktuellsten Eintrag für WildFly (Derzeit 10) auswählen und auf Next klicken

  7. Den Namen könnte man auf WildFly ändern

    Das Home Directory über Browse... im Explorer-Dialog suchen und festlegen

  8. WildFly benötigt ein JDK um zu funktionieren, jedoch ist noch keins zugeordnet.

    Hierzu müssen folgende Schritte erledigt werden:

    1. Alternate JRE auswählen und auf Installed JREs... klicken

    2. Standard VM auswählen und auf Next klicken

    3. auf Directory klicken und den Pfad zum JDK festlegen

      Danach auf Finish klicken

    4. Bei JDK ein Haken machen und auf OK klicken

    5. Zum Schluss sollte es so Aussehen wie im Bild:

      Mit Klick auf Finish sind wir an der Stelle fertig

Anlegen eines Enterprise Application Archive (EAR) - Projekts

  1. Menü File Project... Java EE Enterprise Application Project

  2. Bei Target Runtime WildFly auswählen

    Auf Next klicken

  3. Im folgenden Fenster auf New Module klicken...

  4. In den folgenden Schritten fügen wir die Module EJB und Web hinzu. Die Namen können so belassen werden!

    Nun fügen wir das EJB-Modul dem EAR-Projekt hinzu:

    1. Bei Create default modules den Haken rausnehmen, Enterprise Java Bean wählen und auf Next klicken

    2. Im folgenden Fenster auf Modify... klicken

      Im erscheinenden Fenster einen Haken bei JPA setzen und auf OK klicken

      2 mal auf Next klicken

    3. Als Platform EclipseLink auswählen

      Bei JPA Implementation Library Provided by Target Runtime auswählen

      Bei Connection unsere OracleDataSource auswählen und auf Connect klicken

      Next klicken

    4. Den Haken rausnehmen wie im Bild hervorgehoben (Sofern gesetzt)

      Auf Finish klicken

    Nun fügen wir das Web-Modul dem EAR-Projekt hinzu:

    1. Wieder klicken wir auf New Module...
    2. Bei Create default modules den Haken rausnehmen, Web auswählen und Next klicken
    3. Auf Finish klicken

  5. Nun sollte es wie im Bild aussehen

    Anschließend auf Finish klicken

  6. Das Projekt ist fertig erzeugt und im Projektexplorer sollte es jetzt so aussehen:

Die Datei persistence.xml modifizieren

  1. Hierzu öffnen wir den Zweig ProjektTestEJB in unserem ProjektTest
  2. Darin den Zweig JPA Content öffnen
  3. Nun ein Doppelklick auf persistence.xml
  4. im sich öffnenden Fenster bitte das Tab General aufrufen

    Bei Persistence provider folgendes eintragen:

    org.eclipse.persistence.jpa.PersistenceProvider
  5. Nun rufen wir das Tab Connection auf

    bei JTA data source tragen wir folgendes ein:

    java:/OracleDS
  6. Jetzt rufen wir das Tab Properties auf

    Dort fügen wir über Add folgendes hinzu

    eclipselink.target-server
    JBoss
  7. Im Tab Source sollte es nun wie folgt aussehen:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
        <persistence-unit name="ProjektTestEJB">
            <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <jta-data-source>java:/OracleDS</jta-data-source>
            <properties>
                <property name="eclipselink.target-server" value="JBoss"/>
            </properties>
        </persistence-unit>   
    </persistence>

    Der Name von persistence-unit wird später für den Persistenz Kontext des Entity Manager benötigt. Den sollte man also belassen oder ändern und später ensprechend verwenden. Siehe Beispiel:

    @PersistenceContext(name="ProjektTestEJB")

Nun ist alles erledigt um JPA nutzen zu können!

Entities anlegen lassen

Die Entities die bei mir erstellt werden, müssen nicht zwangsweise eure darstellen. Hier handelt es sich um eines meiner letzten Projekte.

Folgende Schritte sind zu befolgen:

  1. Rechtsklick auf das Teilprojekt ProjektTestEJB : JPA-Tools Generate Entities from Tables...
  2. Im folgenden Fenster sollten alle Tabellen ausgewählt und auf Next geklickt werden

  3. Die folgende Ansicht der Beziehungen können wir übergehen mit Next
  4. In dieser Ansicht müssen wir einen Namen für das Package vergeben. Ich habe mich für entities entschieden

    Und wieder Next

  5. In folgender Ansicht kann man die Entities weiter detailiert modifizieren.

    Da ich für die Tabelle Land eine Sequence mit dem Namen SEQ_Land aus der Oracle DB nutzen möchte, muss eine Änderunge vornehmen, wie im Bild zu sehen ist. Braucht ihr das nicht, dann kann man hier auf Finish klicken

  6. Das Projekt sollte jetzt wie folgt aussehen:

Test der JPA-Funktion

Hier werden wir eine kleine Session Bean und ein Servlet anlegen. Dort setzen wir etwas Beispiel-Code ein, um die JPA-Funktionalität zu testen.

Legen wir eine Session Bean an:

  1. Rechtsklick auf ProjektTestEJB: New Session Bean (EJB 3.x)

    • Java package: beans
    • Classe name: Test
    • State type: Stateless
    • Ein Haken bei Local Business Interface

    Auf Finish klicken

  2. Nun legen wir eine Business-Methode an. Eins vorweg, dies ist leider nicht so komfortabel wie in NetBeans. Aber so schwer ist es nicht...

    1. Ersetze alles innerhalb der Klasse Test mit folgendem:

      @PersistenceContext(unitName = "ProjektTestEJB")
      private EntityManager em;
      
          public String getFlughafenStadtName(String kuerzel)
          {
              Flughafen fH = em.find(Flughafen.class, kuerzel);
              return fH.getStadt();
          }

      Anschließend sollte es wie folgt Aussehen:

      Achtet auf die Imports!

    2. Setzt den Cursor in den Methoden-Kopf der Methode getFlughafenStadtName und bleibt mit dem Mauspfeil auch dort!

      Rechtsklick: Refactor Pull Up...

      Im erscheinden Fenster einfach auf Finish klicken!

      Was haben wir gemacht? Wir haben die Methode getFlughafenStadtName im Interface TestLocal anlegen lassen.

      Nun die Änderungen in Test und TestLocal


      Damit haben wir den Teil für die Session Bean erledigt!

  3. Nun erstellen wir ein Servlet:

    1. Rechtsklick auf das Teilprojekt ProjektTestWeb
    2. New Servlet
    3. Im erscheinenden Fenster folgendes ausfüllen:

      • Java package: servlets
      • Class name: Ausgabe

      Klick auf Finish!

    4. Nun müssen wir das Modul ProjektTestEJB dem Modul ProjektTestWeb bekannt machen

      1. Rechtsklick: ProjektTestWeb Properties
      2. Im Bäumchen den Punkt Java Build Path auswählen
      3. Das Tab Projects wählen und auf Add... klicken
      4. Im sich öffnenden Fenster sollte nun unser ProjektTestEJB ersichtlich sein. Hier einen Haken setzen und auf OK klicken. Danach nochmal auf OK klicken.
    5. Unterhalb von

      public class Ausgabe extends HttpServlet {

      fügen wir folgendes ein:

      @EJB
      private TestLocal tL;

      Bei beiden Einträgen muss ein Import gemacht werden!

      Geht mit dem Mauspfeil auf die roten Wellenlinien und wartet bis eine Blase sich öffnet. Hier den Eintag mit Import anklicken

    6. In der doGet Methode fügen wir folgendes unterhalb der letzten Anweisung ein:

      PrintWriter out = response.getWriter();
      out.println("<p>Der Flugghafen JFK ist in der Stadt: <strong>" + tL.getFlughafenStadtName("JFK") + "</strong></p>");

      Auch hier ist ein Import nötig!

    7. Anschließend sieht es wie folgt aus:

      package servlets;
      
      import java.io.IOException;
      import java.io.PrintWriter;
      
      import javax.ejb.EJB;
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      import beans.TestLocal;
      
      /**
       * Servlet implementation class Ausgabe
       */
      @WebServlet("/Ausgabe")
      public class Ausgabe extends HttpServlet {
      	@EJB
      	private TestLocal tL;
      	
      	private static final long serialVersionUID = 1L;
             
          /**
           * @see HttpServlet#HttpServlet()
           */
          public Ausgabe() {
              super();
              // TODO Auto-generated constructor stub
          }
      
      	/**
      	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
      	 */
      	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		// TODO Auto-generated method stub
      		response.getWriter().append("Served at: ").append(request.getContextPath());
      		PrintWriter out = response.getWriter();
      		out.println("<p>Der Flugghafen JFK ist in der Stadt: <strong>" + tL.getFlughafenStadtName("JFK") + "</strong>/lt;/p>");
      	}
      
      	/**
      	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
      	 */
      	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		// TODO Auto-generated method stub
      		doGet(request, response);
      	}
      
      }
                                      

Jetzt können wir das Projekt starten. Klickt hierzu auf die "Play" Schaltfläche aus der Symbolleiste

Da wir noch keinen Application Server für das Projekt festgelegt haben, werden wir hier dazu aufgefordert.

Wählt WildFly 10 aus und klickt auf Next und anschließend auf Finish

Optionale Änderungen

Folgendes ist für die JPA-Funktionalität nicht nötig aber erhöht den Komfort

Hotdeploy für Wildfly aktivieren

Damit jede Änderung an einem Servlet oder JSP dem Application Server mitgeteilt wird, muss folgende Konfiguration vorgenommen werden:

  1. Menü Window Show View Servers
  2. Doppelklick auf den Server (erste Zeile) (ein Fenster geht auf)
  3. Puplishing aufklappen und "Automatically publish when resources change" auswählen
  4. Application Reload Behavior aufklappen:
    • Haken raus bei "Use default pattern"
    • folgendes in die Textzeile darunter eintragen
      \.jar$|\.class$|\.jsp$
  5. Aplication Server neustarten: Rechtsklick auf den Server und im Kontextmenü Restart auswählen