Moderne Webentwicklung mit Java EE 7: Ein Experiment

Seite 2: Build-System

Inhaltsverzeichnis

Ein wichtiges Feature von Ruby on Rails ist das sehr gut integrierte Build-System. Rake nimmt Entwicklern viele lästige Aufgaben ab. So löst es beispielsweise Abhängigkeiten zu fremden Bibliotheken auf oder migriert die angebundene Datenbank auf die neuste Version des Schemas.

Für das Beispielprojekt in Java wird Gradle diese Rolle übernehmen. Alternativ wäre das weiter verbreitete Maven möglich. Letzteres erfordert jedoch die Konfiguration über XML-Dateien, während Gradle eine gut verständliche und vor allem kurze DSL (Domain Specific Language) nutzt. Der folgende Code-Ausschnitt zeigt ein lauffähiges Build-Skript:

apply plugin: 'java'
apply plugin: 'war'

group = 'it.macke.blog'

sourceCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'

repositories {
mavenCentral()
}

dependencies {
compile 'javax:javaee-api:7.0'
}

Das Skript ist weitgehend selbsterklärend. Die in den ersten beiden Zeilen geladenen Plug-ins sorgen dafür, dass mittels gradle war aus einem Java-Webprojekt ein deploybares WAR-File erstellt werden kann, dessen Name group festlegt. Das Skript erwartet Quelltext, der in UTF-8 kodiert und kompatibel zu Java 8 ist. Eventuell benötigte Bibliotheken werden automatisch aus dem zentralen Maven-Repository heruntergeladen.

Das Beispielprojekt verwendet bewusst keinerlei externe Abhängigkeiten außer der API von Java EE 7. Der Einsatz zusätzlicher Bibliotheken könnte das Projekt eventuell optimieren (s.u.).

Um das Projekt auszuführen, müssen Entwickler es in einen Application Server deployen, der alle zur Laufzeit benötigten Ressourcen und Bibliotheken bereitstellt. Dazu zählen insbesondere die Datenbankverbindung und alle Implementierungen der Java EE 7 API, wie Hibernate für den Datenbankzugriff mit JPA oder Mojarra für die Oberflächen mit JSF. Für das Beispielprojekt kommt Wildfly zum Einsatz, die Community-Variante des JBoss Application Server.

Wildfly bringt eine interne H2-Datenbank mit, die automatisch zur Verfügung steht. Das Beispielprojekt verwendet H2, um eine zusätzliche Konfiguration oder gar die Installation einer Datenbanksoftware zu vermeiden. Das folgende Codebeispiel zeigt die Konfiguration der Datenbank in der Datei META-INF/persistence.xml:

<?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="blog">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>

java:jboss/datasources/ExampleDS ist der JNDI-Name (Java Naming and Directory Interface) der H2-Datenquelle in Wildfly. Die Zugangsdaten sind im Application Server hinterlegt. Entwickler müssen sich somit nicht um die Konfiguration kümmern, sondern können die bereitgestellte Verbindung über einen einfachen Namen ("blog") ansprechen. Der produktive Einsatz der Anwendung würde die Anpassung der Konfiguration in Wildfly auf eine echte Datenbank erfordern. Hibernate – als Abstraktionsschicht zur konkreten Datenbank – kümmert sich daraufhin um die technischen Details.

Die Property hibernate.hbm2ddl.auto weist Hibernate an, die notwendigen Tabellen für die noch zu erstellenden Domänenklassen automatisch zu erzeugen und auch wieder zu entfernen (was im Produktivbetrieb sicherlich anzupassen wäre).

Weitere XML-Dateien sind für die Konfiguration nicht erforderlich. Bisher war für das Java-Projekt nicht viel mehr Konfiguration nötig, als es Ruby on Rails erfordern würde. Entwickler müssen in Rails ebenfalls eine Datenbankverbindung einrichten und ein Build-Skript anlegen. Dort erfolgt die Konfiguration in YAML (Yet Another Markup Language) statt in XML.

Nachdem die Infrastruktur für das Projekt steht, kann die Programmierung beginnen. Hält man die aus Maven bekannten Ordnerstruktur ein, ist Gradle mit ein paar Ergänzungen im Build-Skript, die hier nicht im Detail vorgestellt werden, in der Lage, ein lauffähiges Eclipse-Projekt zu erzeugen.

Die Java-Projektstruktur in Eclipse (Abb. 3)

Es ist in drei Packages aufgeteilt: die Domänenklassen Post und Comment, die Persistenzlogik mit jeweils einem Repository pro Domänenklasse und Controller für die Weboberfläche. Das Beispielprojekt verzichtet auf die Trennung von Domänen- und Persistenzmodell. Das bedeutet, dass die Domänenklassen (z.B. Post) direkt persistiert werden und nicht noch zusätzliche Klassen für die Abbildung auf die Datenbanktabellen (z.B. PostDao) erstellt wurden. In größeren Projekten kann sich das Domänenmodell durchaus vom Persistenzmodell unterscheiden, sodass eine Aufteilung sinnvoll wäre. Die Vorgehensweise hätte jedoch auch viel Code für das Mapping zwischen beiden Modellen zur Folge, die das Beispielprojekt vermeidet.

Die JSF-Seiten liegen im Unterordner "src/main/webapp". Ihre Struktur zeigt Abbildung 4.

Die Web-Projektstruktur in Eclipse (WebProjektstrukturInEclipse.jpg (Abb. 4)