Stoppt die Vorratsdatenspeicherung! Jetzt klicken &handeln! Willst du auch an der Aktion teilnehmen? Hier findest du alle relevanten Infos
und Materialien:

JEE + Maven + Eclipse

.!.

So, heute mal wieder ein Artikel aus dem tiefen Tal der lustigen Softwarefrickeleien. Ich habe mich am Wochenende mal intensiv mit JEE, Eclipse und Maven und dem Zusammenspiel dieser Dinge auseinandergesetzt. Die nächste Version des LinuxTag eTicket-Systems soll voll auf JEE setzen.

Maven mit Eclipse für JEE-Projekte zusammenzubringen ist nicht so ganz einfach. Deswegen hier eine kleine How-To.

Seltsamerweise existieren im Netz keine wirklich verwendbaren
“Kochrezepte” dafür, obwohl es sich aus meiner Sicht um ein
“Standardproblem” handelt.

Ziel ist es, die Vorzüge von Eclipse bei der Entwicklung von JEE-Modulen
zu nutzen (Hotdeployment, Servermanagement, Debugging usw.) und
gleichzeitig die volle Buildfähigkeit über Maven zu erhalten.

Dazu muss man grundlegend einen anderen Weg gehen, als das bei
JSE-Projekten der Fall ist: statt ein Projekt zunächst auf der
Maven-Ebene aufzubauen und dann von Maven die Eclipse-Settings über “mvn
eclipse:eclipse” erzeugen zu lassen, muss ein JEE-Projekt von Eclipse
her aufgebaut werden. Maven ist deutlich flexibler anpassbar als die
JEE-Eclipse-Plugins.

Schritt 1: Eclipse JEE-Projekte anlegen

Über die ganz normalen Wizards wird ein JEE-Projekt mit allen
Untermodulen angelegt. Für das Beispiel gehe ich von folgenden einzelnen
Eclipse-Projekten aus:

  • DemoEJB

    Projekt, das die EJBs enthält. Hier werden (abweichend vom Eclipse-Standard) später auch die Domain-Klassen und die Remote-Stubs der EJB abgelegt. Maven erzeugt beim Releasebuild automatisch ein abgespecktes Client-JAR, dass nur die vom Client benötigten Klassen enthält. Während des Eclipse-Workflows werden die Klassen dieses Moduls vollständig mit dem Client deployt, liegen also zweimal physikalisch auf dem Server, falls der Client eine JEE-Serveranwendung wie z.B. ein WAR ist. (einmal beim EJB, einmal beim Client). Das ist verschmerzbar, stört nicht und ist durch die Eclipse-Governance auch sicher konsistent.

  • DemoServlet
    Der Client für die EJBs in Form einer JEE-Weblayer-Anwendung. Hier sind Standard-Servlets und/oder JSPs enthalten, die über JNDI auf die EJBs zugreifen. Externe Clients sind ebenfalls möglich, aber der JEE-Client ist der in diesem Fall komplexere Fall, weil das WAR ebenfalls deployt werden muss.
  • DemoEAR
    Das umgebende EAR-Projekt, dass aus dem EJB und dem WAR des Clients ein deploybares EAR-Archiv erzeugt. Da Maven kein gemeinsames Artefakt- und POM-Multiprojekt erlaubt, ist das EAR-Projekt ebenfalls ein Maven-Subprojekt.

Beim Erstellen der Projekte muss auf die Projektabhängigkeit geachtet
und ggf. angepasst werden. Eclipse geht im Standardfall davon aus, dass
Domainklassen und Stub-Interfaces im Client angesiedelt sind. Maven
erwartet diese Klassen aber im Serverprojekt und generiert lieber daraus
ein getrenntes Client-JAR für den Client mit diesen Klassen. Aus meiner
Sicht sauberer und Eclipse auch einfach beibringbar ist der Maven-Weg.
Dazu müssen die Abhängigkeiten folgendermaßen eingestellt sein:

   DemoEAR     --hat Abhängigkeit--> (DemoEJB, DemoServlet).
   DemoServlet --hat Abhängigkeit--> (DemoEJB).


   DemoEJB hat keine definierten Abhängigkeiten.

Sind die Abhängigkeiten eingestellt müssen nun die Pfade “Maven-like”
angepasst werden. Dazu müssen die Java-Sources von den restlichen
Resources getrennt und im üblichen Verzeichnisschema angeordnet werden.
Dies ist über die Projekt-Properties unter “Java Build Path -> Source”
zu erledigen.

Mit der jetzt vorliegenden Einstellung kann dann ein Deployment-Server
definiert werden und das Projekt über Eclipse normal genutzt werden.
Hot-Deployment und Debugging funktioniert direkt aus Eclipse heraus.

Als nächstes müssen die Maven-Einstellungen hinzugefügt werden, damit
das Gesamtprojekt per Maven bau- und deploybar wird.

Schritt 2: Maven-Konfiguration

Die Verzeichnisstruktur in Eclipse sieht im Moment folgendermaßen aus:


    - workspace
      + DemoEAR
      + DemoEJB
      + DemoServlet

Für die Maven-Konfiguration legen wir ein Hüllprojekt um die drei
Einzelprojekte. Dieses Hüllprojekt ist für Eclipse nicht notwendig und
nur für die “Projektklammer” des Multi-Projekts für Maven nötig. Aus
diesem Grund wird dieses Hüllprojekt am besten von Hand angelegt und
über die Kommandozeilentools ins SVN eingecheckt.

Für die Entwicklung bedeutet das, dass das Arbeiten und Bauen mit Maven
und Eclipse leicht unterschiedlich erfolgt. Die Zielverzeichnis bzw.
Projektstruktur sieht so aus:


    - DemoJEE
      + DemoEAR
      + DemoEJB
      + DemoServlet
      pom.xml

In Eclipse wird dann nicht das Hüllprojekt ausgecheckt und genutzt,
sondern nur die drei Subprojekte. Die Einstellungen des Hüllprojekts
sind nur für einen Maven-Build nötig. In diesem Fall wird das
Gesamtprojekt ausgecheckt und per “mvn package” das resultierende
EAR-Archiv im Subprojekt “DemoEAR” gebaut.

POM des Hüllprojekts

Die POM des Hüllprojekts ist recht simpel. Sie besteht aus einem
einfachen Multi-POM mit zusätzlichen Repository-Einstellungen:


<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.tarent</groupId>
  <version>1.0-SNAPSHOT</version>
  <artifactId>DemoJEE</artifactId>
  <packaging>pom</packaging>
  <name>project</name>
  <modules>
    <module>DemoEJB</module>
    <module>DemoServlet</module>
    <module>DemoEAR</module>
  </modules>
  <repositories>
    <repository>
      <id>jboss-repository</id>
      <name>jboss repository</name>
      <url>http://repository.jboss.com/maven2/</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>
</project>

Das JBoss-Repository ist für die Abhängigkeiten zu den JEE-Bibliotheken
nötig, die in den Subprojekten definiert sind. Das Projekt wird damit
gegen die JEE-JBoss-Implementierung gebaut. Das bedeutet explizit nicht,
dass die resultierenden JEE-Module nicht in anderen Appservern laufen,
die Bibliotheken werden als “provided” dort vorausgesetzt und nicht mit
gepackaged. JBoss bietet eine zertifizierte JEE 1.5-Implementierung.
Trotzdem sollten wir uns dafür im nicht-JBoss-Fall noch ein paar
Gedanken zur QS machen, das nur am Rande.

POM von DemoEJB

Das DemoEJB-Projekt ist ein einfaches Maven-Projekt, dass das EJB-Plugin
verwendet, um ein EJB-Jar zu erstellen.


<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.tarent.DemoJEE</groupId>
  <artifactId>DemoEJB</artifactId>
  <packaging>ejb</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>enterprise java bean</name>
  <parent>
    <groupId>de.tarent</groupId>
    <artifactId>DemoJEE</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <build>
    <sourceDirectory>src/main/java</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-ejb-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
            </manifest>
          </archive>
          <ejbVersion>3.0</ejbVersion>
          <generateClient>true</generateClient>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>javax.persistence</groupId>
      <artifactId>persistence-api</artifactId>
      <version>1.0</version>
      <scope>provided</scope>
    </dependency>
   <dependency>
      <groupId>javax.ejb</groupId>
      <artifactId>ejb-api</artifactId>
      <version>3.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>

Falls weitere JEE-Abhängigkeiten benötigt werden, können diese hier
hinzugefügt werden. Als Parent wird das Hüllprojekt angegeben. Die
JBoss-Repository-Definitionen werden von dort geerbt.

Die “generateClient”-Einstellung sorgt dafür, dass ein zusätzliches
“virtuelle” Artefakt erstellt und dem virtuellen Repository hinzugefügt
wird. Auf dieses referenzieren wir dann später in den Abhängigkeiten des
Clients. Dieses spezielle Client-JAR enthält nur die Entities und die
Stubs. In der Konfiguration kann über weitere Parameter noch genauer
angegeben werden, welche Bestandteile des EJB-Codes in den Client
gepackaged werden. Genauere Infos dazu sind in der Plugin-Dokumentation
zu finden.

POM des Clients

Das Client-Projekt “DemoServlet” ist ein Standard-WAR-Projekt, dass aber
zusätzlich eine Abhängigkeit zur zuvor erstellen “virtuellen”
Client-Bibliothek enthält:


    ...
    <dependency>
      <groupId>de.tarent.DemoJEE</groupId>
      <artifactId>DemoEJB</artifactId>
      <version>1.0-SNAPSHOT</version>
      <type>ejb-client</type>
    </dependency>
    ...

Statt “ejb” wird “ejb-client” als Typ angegeben. Würde “ejb” angegeben,
so würde der gesamte Code des EJB-Projektes im resultierenden WAR
mitgepackaged werden.

POM des EAR-Projekts

Das EAR-Projekt baut aus den vorhandenen Artefakten das EAR zusammen und
deployt es optional auch direkt in einem JBoss-Server. Das EAR-Projekt
enthält selbst keinen Quellcode dafür aber die EAR-Deployment-Deskriptoren.


<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.tarent.DemoJEE</groupId>
  <artifactId>DemoEAR</artifactId>
  <packaging>ear</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>ear assembly</name>
  <dependencies>
    <dependency>
      <groupId>de.tarent.DemoJEE</groupId>
      <artifactId>DemoEJB</artifactId>
      <type>ejb</type>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>de.tarent.DemoJEE</groupId>
      <artifactId>DemoServlet</artifactId>
      <type>war</type>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>
  <build>
<plugins>
      <plugin>
        <artifactId>maven-ear-plugin</artifactId>
        <configuration>
<applicationXml>${artifactId}/EarContent/META-INF/application.xml</applicationXml>
          <defaultLibBundleDir>lib</defaultLibBundleDir>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
            </manifest>
          </archive>
          <modules>
            <ejbModule>
              <groupId>de.tarent.JEEDemo</groupId>
              <artifactId>DemoEJB</artifactId>
              <bundleFileName>DemoEJB.jar</bundleFileName>
            </ejbModule>
            <webModule>
              <groupId>de.tarent.JEEDemo</groupId>
              <artifactId>DemoServlet</artifactId>
              <contextRoot>/DemoServlet</contextRoot>
              <bundleFileName>DemoServlet.war</bundleFileName>
            </webModule>
	  </modules>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jboss-maven-plugin</artifactId>
        <configuration>
        <jbossHome>/home/kleinhenz/Bibliothek/jboss-4.2.3.GA</jbossHome>
          <port>8080</port>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Problematisch ist die Einstellung des JBoss-Homedirs. Diese Einstellung
ist im Moment leider nicht extern einstellbar. Allerdings ist die
Nutzung des JBoss-Plugins nur nötig, wenn direkt aus Maven heraus
deployt werden soll.

Bauen und Deployen

Damit ist die Konfiguration insgesamt fertig. Unter Eclipse lassen sich
die Projekte normal mit den Eclipse-Bordmitteln nutzen. Will man einen
Maven-Build vornehmen, so wird das Hüllprojekt ausgecheckt und mit “mvn
package” das Projekt gebaut. Nach dem Vorgang liegt im EAR-Projekt das
fertige EAR-Archiv.

Tags:

Eine Antwort auf “JEE + Maven + Eclipse”

  1. Barnie schreibt:

    Falls Du noch jemand bedarf an ein paar Vorträgen zum Thema JEE6 oder Maven hat habe ich hier zwei Links:

    Maven:
    http://www.loroma.com/loroma/movie.faces?movie=15300#Maven-2-1220057521551

    JEE6:
    http://www.loroma.com/loroma/movie.faces?movie=15503#Productive-Java-EE-6-1221891286879

Kommentar abgeben