In questa guida illustriamo i CloudletRestletPlugin come metodo per aggiungere risorse REST o GraphQL personalizzate all’interno di una Cloudlet e diamo dei cenni sulla loro implementazione.
Panoramica #
Una Cloudlet è in grado di generare risorse GraphQL che consentono operazioni CRUD sui suoi elementi e l’invocazione diretta dei FormActionHandler. A queste si aggiungono i CloudletRestletPlugin, che si basano sul framework Restlet e consentono di soddisfare ulteriori casi d’uso, come la costruzione di uno snippet HTML da far renderizzare a un browser o la generazione di valori casuali.
Al pari degli ScheduledTask, i CloudletRestletPlugin non sono oggetti del modello e vanno implementati direttamente nella base di codice.
Un plugin di questo tipo estende la classe astratta RestletServerResource ed è decorato con l’annotazione @CloudletRestletServerResource:
@CloudletRestletServerResource
public class MyRestletResource extends RestletServerResource {
//...
}
Note implementative #
Per implementare un CloudletRestletPlugin vanno seguite le linee guida relative alla configurazione di un progetto Java e alla sua successiva programmazione nella sezione Ciclo di sviluppo.
Lo sviluppatore deve costruire una nuova classe che estende dal tipo astratto RestletServerResource
, implementando i due metodi astratti getType()
e getUrl()
:
getType()
deve restituire un valore enumerato traPUBLIC_EXT
,PUBLIC_GRAPHQL
,AUTH_EXT
eAUTH_GRAPHQL
. Il valore di ritorno definisce il tipo di risorsa rappresentato dalla classe, la quale può essere pubblica (PUBLIC
) o necessitante di autenticazione (AUTH
), e di natura REST o GraphQL;getUrl()
deve restituire una stringa costituita da un nome semplice (es.myResource
) o un path relativo completo (es.path/to/myResource
). Definisce l’URL presso cui la risorsa sarà disponibile.
L’indirizzo dell’endpoint del plugin è nella forma <CloudletUrl>/<AccessLevel>/api/<ResourceType>/<ResourceUrl>
e viene costruito come segue:
<CloudletUrl>
è l’URL della Cloudlet per cui stiamo realizzando il CloudletRestletPlugin;<AccessLevel>
viene valorizzato apublic
se la risorsa è esposta pubblicamente, o aauth
se la risorsa richiede autenticazione;<ResourceType>
se la risorsa è di tipo REST o GraphQL, viene rispettivamente valorizzato aext
ographql
;<ResourceUrl>
viene valorizzato all’URL restituito dagetUrl()
.
A questo punto va definita la risposta fornita dall’endpoint personalizzato, implementando un ulteriore metodo da annotare con la tipologia di comando HTTP, come @Get
o @Post
: l’annotazione può accettare un parametro di tipo stringa che specifica la formattazione da applicare al risultato; per esempio, indicando @Get("json")
la risposta dovrĂ essere restituita nel formato JSON.
@Get("json")
public String getPerson() {
return "{ \"firstName\" : \"Mario\", \"lastName\" : \"Rossi\"}"
}
All’interno di questo metodo è possibile richiamare i servizi della Cloudlet, che in questo caso non vanno iniettati da costruttore ma sono già forniti nel contesto della risposta. Lo sviluppatore può accedervi direttamente invocando uno dei metodi della classe astratta RestletServerResource
: per esempio il database della Cloudlet, come DataSource, si ottiene invocando getDataSource()
.
Esempio #
Il seguente esempio riunisce tutti i concetti finora mostrati:
@CloudletRestletServerResource
public class MyExtRestletResource extends RestletServerResource {
@Override
public RestletServerResourceType getType() {
return AUTH_EXT;
}
@Override
public String getUrl() {
return "myExt";
}
@Get("json")
public String myService() {
List<String> employeeJsons = new LinkedList<>();
try (Connection c = getDataSource().getConnection()) {
ResultSet rs = c.prepareStatement("SELECT firstName, lastName FROM `employee`").executeQuery();
while (rs.next()) {
String firstName = rs.getString("firstName");
String lastName = rs.getString("lastName");
employeeJsons.add(String.format("{ \"firstName\" : \"%s\", \"lastName\" : \"%s\" }"));
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
String jsonRes = String.join(employeeJsons, ",");
return "[" + jsonRes + "]";
}
}
Stiamo definendo una risorsa REST di tipo autenticato (getType()
restituisce il valore AUTH_EXT
), reperibile all’indirizzo <CloudletUrl>/auth/api/ext/myExt
, che risponde con i nomi e i cognomi degli impiegati memorizzati nella nostra Cloudlet.
La risposta è fornita dal metodo myService()
, che è annotato con @Get("json")
: questo significa che dobbiamo inoltrare una richiesta con il comando HTTP Get, ottenendo una stringa formattata come JSON. All’interno notiamo l’utilizzo del metodo getDataSource()
della classe astratta, che ci fornisce l’accesso al DataSource della Cloudlet, al quale chiediamo l’apertura di una connessione con getConnection()
: la utilizziamo per sottomettere uno statement JDBC che ci restituisce l’intero insieme degli impiegati nella tabella employee
che corrisponde all’omonima classe, proiettandolo sui soli campi firstName
e lastName
.
Fatto ciò, scansioniamo il risultato dello statement trasformando ciascun record in una stringa JSON opportunamente formattata, per poi riunirli tutti in una ulteriore stringa che restituiremo, rappresentante una lista in JSON.
Riferimenti #
Nella presente guida abbiamo mostrato le caratteristiche basilari del framework Restlet, le quali permettono di coprire i casi d’uso più semplici.
Per ulteriori dettagli, rimandiamo alla documentazione di Restlet.