JAX-RS is slechts een API!

1. Overzicht

Het REST-paradigma bestaat al een aantal jaren en krijgt nog steeds veel aandacht.

Een RESTful API kan op een aantal manieren in Java worden geïmplementeerd: je kunt Spring, JAX-RS gebruiken, of je kunt gewoon je eigen kale servlets schrijven als je goed en moedig genoeg bent. Het enige dat u nodig heeft, is de mogelijkheid om HTTP-methoden bloot te leggen - de rest heeft alles te maken met hoe u ze organiseert en hoe u de klant begeleidt bij het aanroepen van uw API.

Zoals je kunt opmaken uit de titel, gaat dit artikel over JAX-RS. Maar wat betekent "gewoon een API"? Het betekent dat de focus hier ligt op het verhelderen van de verwarring tussen JAX-RS en zijn implementaties en op het bieden van een voorbeeld van hoe een goede JAX-RS webapp eruit ziet.

2. Opname in Java EE

JAX-RS is niets meer dan een specificatie, een set interfaces en annotaties die worden aangeboden door Java EE. En dan hebben we natuurlijk de implementaties; enkele van de meer bekende zijn RESTEasy en Jersey.

Als u ooit besluit om een ​​JEE-compatibele applicatieserver te bouwen, zullen de jongens van Oracle u vertellen dat uw server, naast vele andere dingen, een JAX-RS-implementatie moet bieden die de geïmplementeerde apps kunnen gebruiken. Daarom heet het Java Enterprise Edition Platform.

Een ander goed voorbeeld van specificatie en implementatie is JPA en Hibernate.

2.1. Lichtgewicht oorlogen

Dus hoe helpt dit alles ons, de ontwikkelaars? De hulp is dat onze implementaties erg dun kunnen en moeten zijn, zodat de applicatieserver de benodigde bibliotheken kan leveren. Dit is ook van toepassing bij het ontwikkelen van een RESTful API: het uiteindelijke artefact mag geen informatie bevatten over de gebruikte JAX-RS-implementatie.

Natuurlijk kunnen we de implementatie verzorgen (hier is een tutorial voor RESTeasy). Maar dan kunnen we onze applicatie niet meer “Java EE app” noemen. Als er morgen iemand komt en zegt "Ok, tijd om over te schakelen naar Glassfish of Payara, JBoss werd te duur!“, Misschien kunnen we het, maar het wordt geen gemakkelijke klus.

Als we onze eigen implementatie bieden, moeten we ervoor zorgen dat de server weet dat hij zijn eigen implementatie moet uitsluiten - dit gebeurt meestal door een eigen XML-bestand in het implementeerbare bestand te hebben. Onnodig te zeggen dat zo'n bestand allerlei tags en instructies zou moeten bevatten waar niemand niets van af weet, behalve de ontwikkelaars die het bedrijf drie jaar geleden hebben verlaten.

2.2. Ken altijd uw server

We hebben tot nu toe gezegd dat we moeten profiteren van het platform dat ons wordt aangeboden.

Voordat we beslissen welke server te gebruiken, moeten we zien welke JAX-RS-implementatie (naam, leverancier, versie en bekende bugs) het biedt, in ieder geval voor productieomgevingen. Glassfish wordt bijvoorbeeld geleverd met Jersey, terwijl Wildfly of Jboss wordt geleverd met RESTEasy.

Dit betekent natuurlijk dat er wat tijd aan onderzoek wordt besteed, maar het zou maar één keer moeten gebeuren, aan het begin van het project of bij het migreren naar een andere server.

3. Een voorbeeld

Als je wilt beginnen met spelen met JAX-RS, is het kortste pad: heb een Maven webapp-project met de volgende afhankelijkheid in de pom.xml:

 javax javaee-api 7.0 voorzien 

We gebruiken JavaEE 7 omdat er al tal van applicatieservers zijn die het implementeren. Die API-pot bevat de annotaties die u moet gebruiken, die zich in het pakket bevinden javax.ws.rs. Waarom wordt de scope "verstrekt"? Omdat deze jar ook niet in de laatste build hoeft te zijn - we hebben het nodig tijdens het compileren en het wordt door de server geleverd voor de runtime.

Nadat de afhankelijkheid is toegevoegd, moeten we eerst de entry class schrijven: een lege class die zich uitbreidt javax.ws.rs.core.Application en is geannoteerd met javax.ws.rs.ApplicationPath:

@ApplicationPath ("/ api") openbare klasse RestApplication breidt toepassing uit {} 

We hebben het toegangspad gedefinieerd als zijnde / api. Welke andere paden we ook aangeven voor onze bronnen, ze worden voorafgegaan door / api.

Laten we vervolgens een bron bekijken:

@Path ("/ Notificaties") publieke klasse NotificationsResource {@GET @Path ("/ ping") publieke respons ping () {return Response.ok (). Entiteit ("Service online"). Build (); } @GET @Path ("/ get / {id}") @Produces (MediaType.APPLICATION_JSON) openbare reactie getNotification (@PathParam ("id") int id) {return Response.ok () .entity (nieuwe melding (id , "john", "testmelding")) .build (); } @POST @Path ("/ post /") @Consumes (MediaType.APPLICATION_JSON) @Produces (MediaType.APPLICATION_JSON) openbare reactie postNotification (notificatie) {return Response.status (201) .entity (notificatie) .build () ; }}

We hebben een eenvoudig ping-eindpunt om te bellen en te controleren of onze app actief is, een GET en een POST voor een melding (dit is gewoon een POJO met attributen plus getters en setters).

Implementeer deze oorlog op elke applicatieserver die JEE7 implementeert en de volgende opdrachten zullen werken:

curl // localhost: 8080 / simple-jaxrs-ex / api / notificaties / ping / curl // localhost: 8080 / simple-jaxrs-ex / api / notificaties / get / 1 curl -X POST -d '{"id" : 23, "text": "lorem ipsum", "gebruikersnaam": "johana"} '// localhost: 8080 / simple-jaxrs-ex / api / notificaties / post / --header "Content-Type: application / json "

Waar simple-jaxrs-ex de context-root van de webapp is.

Dit is getest met Glassfish 4.1.0 en Wildfly 9.0.1.Final. Houd er rekening mee dat de laatste twee commando's niet werken met Glassfish 4.1.1 vanwege deze bug. Het is blijkbaar een bekend probleem in deze Glassfish-versie met betrekking tot de serialisatie van JSON (als je deze serverversie moet gebruiken, moet je de JSON-marshaling zelf beheren)

4. Conclusie

Houd er aan het einde van dit artikel rekening mee dat JAX-RS een krachtige API is en dat de meeste (zo niet alle) dingen die u nodig hebt al door uw webserver zijn geïmplementeerd. U hoeft uw inzetbaar niet om te zetten in een onhandelbare stapel bibliotheken.

Dit artikel geeft een eenvoudig voorbeeld en de zaken kunnen ingewikkelder worden. U kunt bijvoorbeeld uw eigen marshalers schrijven. Als dat nodig is, zoek dan naar tutorials die uw probleem oplossen met JAX-RS, niet met Jersey, Resteasy of andere concrete implementatie. Het is zeer waarschijnlijk dat uw probleem kan worden opgelost met een of twee annotaties.