Deploy
Sfruttando la specifica delle Servlets 3.0, Jersey mette a disposizione varie alternative per creare un'applicazione JAX-RS. Sfrutteremo il deploy descriptor-less, ossia senza web.xml
, Quindi ci avvarremo delle annotation, nella fattispecie di @ApplicationPath
per annotare la sottoclasse di Application dove possiamo definire la URI di base dell'applicazione web per tutte le risorse JAX-RS.
@ApplicationPath("api")
public class LibraryApplication extends ResourceConfig {
public LibraryApplication() {
packages("it.html.tutorial.library.api");
}
}
In questo modo abbiamo istruito il framework per cercare le risorse che implementano i servizi all'interno del package it.html.tutorial.library.api
ed esporle alla URI /api
.
Il primo servizio di test
Procediamo quindi con l'implementazione del primo servizio. Creiamo una classe all'interno del package configurato sopra ed implementiamo un primo metodo di esempio per cominciare a comprendere lo spirito del gioco.
@Path("test")
public class Test {
@GET
@Path("{name}")
public String test(@PathParam("name") String name) {
return "Ciao " + name.toUpperCase();
}
}
Le risorse definite nella classe saranno disponibili alla URI /test
, quindi, in base alla configurazione fornita sopra alla URI /api/test
. Il metodo definisce una richiesta di tipo GET
ed aggiunge informazioni circa l'URL identificando il parametro name
sul path di accesso al servizio. Per rendere disponibile il valore passato al parametro name
, usiamo l'annotation @PathParam
, in modo da renderlo disponibile all'interno del metodo.
Avviamo Jetty con il comando:
$ mvn jetty:run
E colleghiamoci tramite un browser all'URL:
http://localhost:8080/api/test/eleonora
Se tutto è andato per il verso giusto dovremmo ricevere come risposta:
Ciao ELEONORA
Testing
Nel caso di metodi HTTP di tipo GET
il browser ci consente egregiamente di effettuare i test del caso. Nel caso di richieste di tipo POST
, avremo invece la necessità di arricchire la chiamata con un payload
. Proviamo, quindi, ad effettuare lo stesso test con curl, sarà molto comodo in seguito per modificare rapidamente il payload e gli header delle richieste HTTP. Apriamo un terminale e lanciamo il comando:
$ curl -v http://localhost:8080/api/test/eleonora
Vedremo i dettagli a livello HTTP della request e della response
Come possiamo vedere dalla figura, ci sono tutte le informazioni di nostro interesse. Abbiamo gli header relativi alla request e quelli relativi alla resposne nonché l'output. Vedremo poi come sia possibile passare anche il payload tramite l'opzione -d
. Curl mette a disposizione tutta una serie di opzioni in grado di simulare le tipiche richieste di un browser web.
Gli oggetti
Prima di procedere con l'implementazione dei metodi utili al nostro progetto, vediamo come ricevere ed inviare richieste complesse.
Il provider MOXy si occupa di tradurre oggetti Java in JSON. Facciamo un esempio. Il seguente JSON:
{
"id": 1,
"title": "Harry Potter and the Philosopher's Stone",
"language": "english"
}
corrisponde alla classe Java Book
.
public class Book {
private long id;
private String title;
private String language;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
Questa classe sarà possibile sfruttarla sia nelle request che nelle response, inserendola come parametro di input / output dei metodi. Pertanto, per implementare un metodo che risponde ad una POST
è possibile usare una classe bean come parametro di input del metodo, ovvero, per rispondere con una risorsa, in seguito ad una GET
possiamo specificare la classe come parametro di output del metodo.
È possibile anche utilizzare oggetti custom, ad esempio nel caso degli author
, avremmo la classe Author
.
public class Author {
private long id;
private String name;
private String surname;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
Possiamo quindi usare la classe Author
per mappare la lista di autori di un libro nella classe Book
.
public class Book {
...
private List<Author> authors;
public List<Author> getAuthors() {
return authors;
}
public void setAuthors(List<Author> authors) {
this.authors = authors;
}
}
Integrando di conseguenza il JSON.
{
"id": 1,
"title": "Harry Potter and the Philosopher's Stone",
"language": "english",
"authors": [{
"id": 1,
"name": "Joanne",
"surname": "Rowling"
}]
}