Quarkus & Couchbase: a simple REST example
CLOUD & DEVOPS
Quarkus & Couchbase: a simple REST example
event 20/04/2023
In uno degli eventi in cui sono stato nei mesi scorsi ho avuto modo di conoscere dei colleghi che lavorano per Couchbase. Conoscevo il prodotto di fama ma non avevo mai avuto occasione di utilizzarlo, quindi mi sono fatto raccontare brevemente le caratteristiche e devo dire che è stato interessante. Ho invitato i ragazzi a passare da noi in @ExtraRed per raccontarci i loro prodotti e saranno infatti ospiti di uno dei nostri Symposium, evento che organizzo mensilmente per raccontare tecnologie, metodologie, progetti e tanto altro a tutti i colleghi.
Per chi non lo conoscesse Couchbase è un database NoSQL, open source e distribuito, progettato per fornire una gestione dei dati rapida, scalabile e flessibile, e dalle prestazioni molto elevate. Utilizza un modello di dati basato su documenti, in cui i dati sono organizzati in documenti JSON, che possono essere facilmente scalati in modo orizzontale su più nodi. È inoltre in grado di gestire grandi quantità di dati in modo affidabile e consente la ridondanza dei dati e la tolleranza ai guasti, grazie all’integrazione nativa per kubernetes, così come per openshift, per il quale è presente un operator dedicato che rende semplicissima e veloce la creazione di un cluster.
A me interessa particolarmente la parte applicativa, specialmente l’uso della tecnologia come database e per questo motivo ho iniziato a fare qualche test di utilizzo con quarkus, tecnologia Java cloud native che utilizziamo massivamente. L’idea era di fare una semplicissima interfaccia REST per scrivere e leggere file json sul database ma siccome ho trovato pochissimi esempi ho deciso di fare questo breve articolo per condividere la mia esperienza, sperando possa essere utile anche per altri.
Trovate in fondo il link al repository su github con il codice dell’esempio.
Come dicevo si tratta di un semplice progetto che ho creato tramite il generatore di quarkus stesso come progetto maven. Ho poi usato la libreria (che è ancora in alpha) di connessione a couchbase “quarkus-couchbase”, semplicemente aggiungendo nel pom la dependency relativa:
<dependency> <groupId>com.couchbase</groupId> <artifactId>quarkus-couchbase</artifactId> <version>1.0.0-alpha.1</version> </dependency>
Come vedete nelle info della libreria stessa si configura semplicemente aggiungendo le properties nel file “application.properties”
quarkus.couchbase.connection-string=localhost quarkus.couchbase.username=username quarkus.couchbase.password=password
L’utilizzo della libreria è piuttosto semplice, e troverete quanto vi descrivo nella classe “QuarkusCouchbaseService” dove sono definiti i metodi REST del servizio:
la libreria ci consente di fare l’injection del Cluster
- tramite questo recuperiamo il bucket sul quale vogliamo leggere/scrivere
- a questo punto usiamo i metodi get e di upsert della collection, rispettivamente per leggere e scrivere i file che abbiamo ricevuto via REST
@Inject Cluster cluster; @ConfigProperty(name = "couchbase.bucketName") String couchbaseBucketName; @GET @Path("/getFile/{id}") @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Gets a file", description = "Retrieves a json file by id") @APIResponses(value = { @APIResponse(responseCode = "200", description = "Success", content = @Content(mediaType = "application/json")), @APIResponse(responseCode = "404", description="File not found", content = @Content(mediaType = "application/json")) }) public Response getFile(@PathParam("id") String id) { var bucket = cluster.bucket(couchbaseBucketName); var collection = bucket.defaultCollection(); try { return Response.ok(collection.get(id).contentAsObject().toString()).build(); } catch (DocumentNotFoundException e){ return Response.status(Response.Status.NOT_FOUND.getStatusCode(),"{\"error\":\"Not Found\"}").build(); } } @POST @Path("/sendFile") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Store File", description = "Store a json file into database, return the id of the new element") @APIResponses(value = { @APIResponse(responseCode = "200", description = "Success", content = @Content(mediaType = "application/json")), @APIResponse(responseCode = "404", description="File not found", content = @Content(mediaType = "application/json")) }) public Response storeFile(String body) { var bucket = cluster.bucket(couchbaseBucketName); var collection = bucket.defaultCollection(); String id = UUID.randomUUID().toString(); JsonObject jsonObj = JsonObject.fromJson(body); MutationResult upsertResult = collection.upsert(id,jsonObj); return Response.ok("{\"id\":\"" + id +"\"}").build(); }
Notare che nel caso della insert ho creato un id generico, che dovrà poi essere utilizzato come parametro della GET per recuperare il file JSON puntuale. Questo perché non viene generato un identificativo in maniera automatica da parte del server, ma deve essere specificato esplicitamente in fase di creazione.
Tutto qua, per fare le varie prove poi ho semplicemente utilizzato l’immagine docker di Couchbase che si trova su docker hub, ho fatto girare il database tramite docker in locale, creato un bucket e configurato gli accessi come specificato sopra.
A questo punto è possibile scrive e recuperare file sul db, magari con postman o semplicemente con delle curl:
scriviamo un file sul db:
curl --location --request POST 'http://localhost:8080/quarkus/sample/sendFile' \ --header 'Content-Type: application/json' \ --data-raw '{ "prova":123, "test":"stringa" }'
la risposta sarà simile a questa:
{ "id": "f8b980eb-1fa0-4070-bcd6-ff3fdce23faf" }
a questo punto testiamo il recupero del file:
curl --location --request GET 'http://localhost:8080/quarkus/sample/getFile/f8b980eb-1fa0-4070-bcd6-ff3fdce23faf' \ --data-raw ''
che ci darà questa risposta:
{ "test": "stringa", "prova": 123 }
Questo è tutto, spero sia stato utile. Se avete suggerimenti o proposte sono le benvenute, magari un approfondimento su quarkus per esempio.
Link Utili:
altri articoli sull'argomento