JAX-RS ist nur eine API!

JAX-RS ist nur eine API!

1. Überblick

Das REST-Paradigma gibt es schon seit einigen Jahren und es wird immer noch viel beachtet.

Eine RESTful-API kann auf verschiedene Arten in Java implementiert werden: Sie können Spring, JAX-RS verwenden oder einfach Ihre eigenen nackten Servlets schreiben, wenn Sie gut und mutig genug sind. Alles, was Sie benötigen, ist die Möglichkeit, HTTP-Methoden verfügbar zu machen. Im Rest geht es darum, wie Sie sie organisieren und wie Sie den Client beim Aufrufen Ihrer API leiten.

Wie Sie aus dem Titel ersehen können, behandelt dieser Artikel JAX-RS. Aber was bedeutet "nur eine API"? Das bedeutet, dass der Fokus hier darauf liegt, die Verwechslung zwischen JAX-RS und seinen Implementierungen zu klären und ein Beispiel dafür zu bieten, wie eine richtige JAX-RS-Webapp aussieht.

2. Aufnahme in Java EE

JAX-RS ist nichts weiter als eine Spezifikation, eine Reihe von Schnittstellen und Anmerkungen, die von Java EE angeboten werden. Und dann haben wir natürlich die Implementierungen; Einige der bekannteren sindRESTEasy undJersey.

Wenn Sie sich jemals für den Bau eines JEE-kompatiblen Anwendungsservers entscheiden, werden die Kollegen von Oracle Ihnen mitteilen, dass Ihr Server unter anderem eine JAX-RS-Implementierung für die bereitgestellten Apps bereitstellen sollte. Aus diesem Grund heißt es Java Enterprise EditionPlatform.

Ein weiteres gutes Beispiel für Spezifikation und Implementierung istJPA undHibernate.

2.1. Leichte Kriege

Wie hilft uns das alles, den Entwicklern? Die Hilfe besteht darin, dass unsere Deployables sehr dünn sein können und sollten, sodass der Anwendungsserver die benötigten Bibliotheken bereitstellt. Dies gilt auch für die Entwicklung einer RESTful-API: Das endgültige Artefakt sollte keine Informationen zur verwendeten JAX-RS-Implementierung enthalten.

Natürlich können wir die Implementierung bereitstellen (hereist ein Tutorial für RESTeasy). Dann können wir unsere Anwendung aber nicht mehr "Java EE App" nennen. Wenn morgen jemand kommt und "Ok, time to switch to Glassfish or Payara, JBoss became too expensive!" sagt, können wir das vielleicht tun, aber es wird keine leichte Aufgabe.

Wenn wir unsere eigene Implementierung bereitstellen, müssen wir sicherstellen, dass der Server seine eigene ausschließt - dies geschieht normalerweise, indem eine proprietäre XML-Datei in der implementierbaren Datei vorhanden ist. Selbstverständlich sollte eine solche Datei alle möglichen Tags und Anweisungen enthalten, von denen niemand etwas weiß, außer den Entwicklern, die das Unternehmen vor drei Jahren verlassen haben.

2.2. Kennen Sie immer Ihren Server

Wir haben bisher gesagt, dass wir die angebotene Plattform nutzen sollten.

Bevor Sie sich für einen Server entscheiden, sollten Sie überprüfen, welche JAX-RS-Implementierung (Name, Hersteller, Version und bekannte Fehler) er bietet, zumindest für Produktionsumgebungen. Zum Beispiel wird Glassfish mit Jersey geliefert, während Wildfly oder Jboss mit RESTEasy geliefert werden.

Dies bedeutet natürlich ein wenig Zeit für die Recherche, sollte jedoch nur einmal durchgeführt werden, zu Beginn des Projekts oder bei der Migration auf einen anderen Server.

3. Ein Beispiel

Wenn Sie mit JAX-RS spielen möchten, ist der kürzeste Weg: Haben Sie ein Maven-Webapp-Projekt mit der folgenden Abhängigkeit inpom.xml:


    javax
    javaee-api
    7.0
    provided

Wir verwenden JavaEE 7, da es bereits viele Anwendungsserver gibt, die es implementieren. Diese API-JAR enthält die Anmerkungen, die Sie verwenden müssen, im Paketjavax.ws.rs. Warum wird der Geltungsbereich „bereitgestellt“? Da dieses JAR auch nicht im endgültigen Build enthalten sein muss, benötigen wir es zur Kompilierungszeit und es wird vom Server für die Laufzeit bereitgestellt.

Nachdem die Abhängigkeit hinzugefügt wurde, müssen wir zuerst die Eintragsklasse schreiben: eine leere Klasse, diejavax.ws.rs.core.Application erweitert und mitjavax.ws.rs.ApplicationPath: kommentiert wird

@ApplicationPath("/api")
public class RestApplication extends Application {
}

Wir haben den Eingabepfad als/api. definiert. Unabhängig davon, welche anderen Pfade wir für unsere Ressourcen deklarieren, wird ihnen/api vorangestellt.

Als nächstes sehen wir uns eine Ressource an:

@Path("/notifications")
public class NotificationsResource {
    @GET
    @Path("/ping")
    public Response ping() {
        return Response.ok().entity("Service online").build();
    }

    @GET
    @Path("/get/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getNotification(@PathParam("id") int id) {
        return Response.ok()
          .entity(new Notification(id, "john", "test notification"))
          .build();
    }

    @POST
    @Path("/post/")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response postNotification(Notification notification) {
        return Response.status(201).entity(notification).build();
    }
}

Wir haben einen einfachen Ping-Endpunkt zum Aufrufen und Überprüfen, ob unsere App ausgeführt wird, ein GET und ein POST für eine Benachrichtigung (dies ist nur ein POJO mit Attributen plus Gettern und Settern).

Stellen Sie diesen Krieg auf einem beliebigen Anwendungsserver bereit, der JEE7 implementiert, und die folgenden Befehle funktionieren:

curl http://localhost:8080/simple-jaxrs-ex/api/notifications/ping/

curl http://localhost:8080/simple-jaxrs-ex/api/notifications/get/1

curl -X POST -d '{"id":23,"text":"lorem ipsum","username":"johana"}'
  http://localhost:8080/simple-jaxrs-ex/api/notifications/post/
  --header "Content-Type:application/json"

Wobei simple-jaxrs-ex das Kontextstammverzeichnis der Webapp ist.

Dies wurde mit Glassfish 4.1.0 und Wildfly 9.0.1.Final getestet. Bitte beachten Sie, dass die letzten beiden Befehle aufgrund des Fehlers vonthisnicht mit Glassfish 4.1.1 funktionieren. Es ist anscheinend ein bekanntes Problem in dieser Glassfish-Version in Bezug auf die Serialisierung von JSON (wenn Sie diese Serverversion verwenden müssen, müssen Sie das JSON-Marshalling selbst verwalten).

4. Fazit

Denken Sie am Ende dieses Artikels daran, dass JAX-RS eine leistungsstarke API ist und die meisten (wenn nicht alle) benötigten Dinge bereits auf Ihrem Webserver implementiert sind. Sie müssen Ihr Deployable nicht in einen nicht verwaltbaren Stapel von Bibliotheken verwandeln.

Dieser Artikel stellt ein einfaches Beispiel dar und die Dinge könnten komplizierter werden. Zum Beispiel möchten Sie vielleicht Ihre eigenen Marshaller schreiben. Suchen Sie bei Bedarf nach Tutorials, die Ihr Problem mit JAX-RS lösen, nicht mit Jersey, Resteasy oder einer anderen konkreten Implementierung. Es ist sehr wahrscheinlich, dass Ihr Problem mit ein oder zwei Anmerkungen gelöst werden kann.