Adam Bien Selbstständig

Auch wenn man sich mit Java EE voll auf die Fachlichkeit fokussieren kann, muss man es überhaupt nicht.

Heute erlauben Konventionen einen vollständigen Verzicht auf XML, wenige Annotationen verdrängen Interfaces, die Unabhängigkeit des Java-EE-Frameworks ist ohne jeglichen Einsatz von Patterns out-of-the-box gegeben. Manche Architekten fühlen sich ein wenig vernachlässigt, denn meist passt die Architektur vollständig auf eine Folie. Ihre Sorgen sind jedoch unbegründet. Mit ein wenig Kreativität kann man immer noch komplizierte Anwendungen für triviale Anwendungsfälle mit Java 8 und Java EE entwickeln.

Fangen wir beim Build-System für unsere Gästebuchanwendung an. Leider ist Maven resistent gegen jegliche Kreativität. Auch komplexe Projekte lassen sich mit der Konfiguration aus Listing 1 bauen. Lediglich Test-Scope-Abhängigkeiten werden in den Projekten benötigt. Es müssen keine Plug-ins oder Profile konfiguriert werden. WARs sind die neuen EARs. In javaee-api sind bereits sämtliche Compile-Scope-Abhängigkeiten enthalten. Ein super-POM zur Pflege einer einzigen provided-Abhängigkeit mit einer festen Version und wenigen Testabhängigkeiten wird nicht benötigt.

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.airhacks</groupId>
  <artifactId>guestbook</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <dependencies>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>guestbook</finalName>
  </build>
  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <failOnMissingWebXml>false</failOnMissingWebXml>
  </properties>
</project>

Webframeworks 2.0

Als ich im Jahr 2002 die Artikelserie „J2EE-Patterns“ für das Java Magazin geschrieben habe, gehörte es auch noch zum guten Ton, ein Projekt mit der Entwicklung eines kleinen Webframeworks zu starten. Aus Webframeworks wurden Services. Die folgende Klassendefinition aktiviert und konfiguriert einen HTTP-Endpunkt mit einer JAX-RS-2.x-Konfiguration:

@ApplicationPath("resources")
public class JAXRSConfiguration extends Application {}

web.xml wird somit nur noch in Ausnahmefällen benötigt.

Die Persistenz

Ein annotiertes POJO übernimmt sowohl die Persistierung als auch die JSON- und XML-Serialisierung der Einträge. Sogar die geschätzten Getter/Setter sind optional (Listing 2).

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@NamedQuery(name = GuestEntry.findAll, query = "SELECT g FROM GuestEntry g")
public class GuestEntry {
  public final static String findAll = "GuestEntry.findAll";
  @Id
  @GeneratedValue
  private long id;
  private String content;

  public GuestEntry(String content) {
    this.content = content;
  }
  protected GuestEntry() {}
}

Die Struktur der Entität bestimmt das Layout der Datenbank. Es wird vernünftigerweise angenommen, dass alle Felder einer persistenten Klasse auch persistent sind. Es ist keine weitere Konfiguration notwendig. Auch die Angabe der Datenbank ist optional, denn dafür existiert ebenfalls ein Defaultwert. In der Praxis sieht jedoch eine minimale Konfiguration der Persistenz folgendermaßen aus:

<persistence>
  <persistence-unit name="guests" transaction-type="JTA">
    <jta-data-source>jdbc/sample</jta-data-source>
    <properties>
      <property name="javax.persistence.schema-generation.database.action" value="create"/>
    </properties>
  </persistence-unit>
</persistence>

Das Verhalten

Einen direkten Zugriff auf die Persistenz erhält ein POJO mit dem annotiertem Feld EntityManager. Die @PersistenceContext-Annotation erlaubt dem Server die Übergabe der mit der persistence.xml-konfigurierten Instanz eines EntityManager direkt an das Feld. Da nur eine Konfiguration und eine PersistenceUnit exisitieren, reicht eine leere Annotation völlig aus (Listing 3).

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class GuestService {
  @PersistenceContext
  EntityManager em;
  public GuestEntry save(GuestEntry entry) {
    return this.em.merge(entry);
  }
  public List all() {
    return this.em.
      createNamedQuery(GuestEntry.findAll, GuestEntry.class).
      getResultList();
  }
  public GuestEntry find(long id) {
    return this.em.find(GuestEntry.class, id);
  }
}

Die @Stateless-Annotation auf der Klasse GuestService erhöht nicht nur die Performance der Anwendung, sondern bringt gleich eine Reihe von Querschnittsaspekten wie automatische Transaktionssteuerung, Nebenläufigkeit und insbesondere Monitoring aller Methoden mit.

Den vollständigen Artikel lesen Sie in der Ausgabe:

Java Magazin 2.17 - "Mehr geht immer"

Alle Infos zum Heft
579757467Ein Java-EE-Projekt mit Augenzwinkern
X
- Gib Deinen Standort ein -
- or -