Die wichtigsten Neuerungen in der Java Enterprise Edition 7

Sprachen  –  9 Kommentare
Anzeige

Rund dreieinhalb Jahre sind seit dem letzten großen Versionssprung der Java Enterprise Edition (Java EE) vergangen. Eine auf Entwicklerperformance und Vereinfachungen ausgelegte Java EE 6 sollte durch das Thema "Cloud" in Java EE 7 technisch stärker werden. Die Pläne stellten sich erst spät als zu ambitioniert heraus. Somit enthält die Mitte April fertiggestellte Version kaum grundlegend Neues und ist lediglich eine konsequente Abrundung der vorhandenen Funktionen.

Die Java Enterprise Edition 7 entstand erstmals komplett unter Oracles Obhut. Sie umfasst als sogenannter "Umbrella" eine Menge einzelner Techniken und liefert die grundlegenden Regelungen für ihre Zusammenarbeit. Seit der Einführung der Java-EE-Plattform war eines der Hauptziele, den Entwickler von allgemeinen Infrastrukturaufgaben zu befreien. Das ermöglicht ein Container-Modell, das Zugriff und Verwaltung auf Ressourcen abstrahiert und vereinfacht. Über die Jahre wurden die Container-APIs vereinfacht, und auch Java EE 7 folgt diesem Trend. Die Ressourcendefinitionen wurden erweitert, und Applikationsserver stellen ab jetzt eine vorkonfigurierte Standard-Datenbankund eine JMS ConnectionFactory zur Verfügung. Das dürfte das Entwickeln vereinfachen und dem Programmierer eine Menge Konfigurationsarbeit ersparen.

Zu den 28 Spezifikationen in Java EE 6 sind vier vollständig neue hinzugekommen. Bei drei bestehenden wurden große inhaltliche Erweiterungen vorgenommen, die einen großen Versionssprung rechtfertigen. Bei den verbleibenden haben die Entwickler weitgehend Modellpflege betrieben. Die in Java EE 6 zum Entfernen vorgeschlagenen Spezifikationen sind in der neuen Version als "optional" gekennzeichnet und somit nicht mehr verpflichtend umzusetzen (EJB Entity Beans, JAX-RPC 1.1, JAXR 1.0 und Java EE Application Deployment 1.2).

Neu hinzugekommen sind APIs zur Arbeit mit angesagten Webtechniken. Neben vollwertigen Spezifikationen wie WebSockets (JSR 356) und JSON (JSR 353) hat man die HTML-5-Unterstützung in den JavaServer Faces (JSF) eingebaut. Das Thema Batch-Verarbeitung hat ebenfalls Einzug in die Plattform gehalten. Der JSR 352 standardisiert ein Programmiermodell für Batch-Anwendungen und bietet eine Laufzeitumgebung für Planung und Ausführung entsprechender Jobs. Einen verbesserten Zugriff auf die Ressourcen der Container ermöglichen die Concurrency Utilities. Mit der API lässt sich nunmehr zuverlässig und in Synchronisation mit den Containern mit Threads in Java EE arbeiten.

Die wichtigsten Änderungen auf einen Blick (Abb. 1)

Obwohl JAX-RS schon in der letzten Java-EE-Version verfügbar war, enthält die Java API for RESTful Web Services (JAX-RS) 2.0 wichtige Neuerungen, die einen großen Versionssprung rechtfertigen. Herausstechendes Merkmal ist die neue Client API. Mit ihr lässt sich aus Java heraus direkt auf Endpoints zugreifen. Die Notwendigkeit von Drittanbieter-Bibliotheken entfällt somit. Im folgenden Beispiel wird ein neuer Client erstellt und eine Anfrage mit zwei Parametern an den Server Endpoint gestellt.

Client client = ClientFactory.newClient();
String name = client.target("/category/{number}/name")
.resolveTemplate("number", "5")
.queryParam("humanReadable", "true")
.request()
.get(String.class);

Neu hinzugekommen ist die asynchrone Bearbeitung von Requests zwischen Client und Server. In Anlehnung an die asynchronen Funktionen seit Servlet 3.0 wird sie mit AsyncRequest erledigt:

@GET
@Produces("application/plain")
public void longRunning(@Suspended final AsyncResponse ar) {
Executors.newSingleThreadExecutor().submit(
new Runnable() {
@Override
public void run() {
longRunning();
ar.resume("Hello heise Developer!");
}
});
}

Mit Message-Filtern und Entity-Interceptors kann man auf Request und Response zugreifen und beide serverseitig bearbeiten. Aber auch beliebte Aspekte wie Logging können Entwickler elegant mit Filtern umsetzen.

@Provider
class LoggingFilter implements RequestFilter {

@Override
public FilterAction preFilter(FilterContext context) throws IOException {
log(ctx.getRequest());
return FilterAction.NEXT;

}
//...
}

Dieser Filter ist dann nur noch über einen @Qualifyer zu binden und lässt sich direkt an einer JAX-RS-Ressource verwenden:

@Logged
@GET
@Produces("text/plain")
@Path("/hello")
public String hello(){
return "Hello @heisedc!";
}

Die Arbeit mit eingebauten Klassen wie String ist damit vergleichsweise einfach. Wird mit eigenen Objekten gearbeitet, ist das Mapping zwischen diesen und der serialisierten Ausgabe (JSON, XML) manuell zu erledigen. Die technischen Möglichkeiten schafft die Spezifikation mithilfe sogenannter Entity Provider. In ihnen lässt sich die Nutzlast der Nachrichten vom einen in das andere Format umwandeln. Analog dazu wurden die beiden zuständigen APIs MessageBodyReader und MessageBodyWriter benannt. Für ein fiktives Objekt "Person" würde ein entsprechender Reader folgendermaßen aussehen:

@Provider
@Produces("application/json")
public class PersonReader implements MessageBodyReader<Person> {
//...

@Override
public void readFrom(Person p, Class<Person> type, Type t, Annotation[]
as, MediaType mt, MultivaluedMap<String, Object> mm, OutputStream out)
throws IOException, WebApplicationException {
//...
}

Die Entity Provider bieten dabei lediglich den Einsprung in JAX-RS an. Das konkrete De-/Serialisieren der Objekte ist noch zu implementieren. Leider bieten weder Spezifikation noch Referenzimplementierung hierfür etwas serienmäßig an. Der Entwickler hat die Wahl zwischen bestehenden Mechanismen, wie ihn beispielsweise EclipseLink mit MOXy anbietet, oder er kann selbst tätig werden.

Anzeige