Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Client per la Java Virtual Machine

Sfruttare la libreria Nodes per implementare un client GraphQL su Java: ecco tutto ciò che serve per eseguire query e mutation.
Sfruttare la libreria Nodes per implementare un client GraphQL su Java: ecco tutto ciò che serve per eseguire query e mutation.
Link copiato negli appunti

American Express ha sviluppato (e continua a sviluppare) un client GraphQL per i linguaggi
supportati dalla Java Virtual Machine, impiegabile pertanto in applicazioni Java,
Kotlin, Scala ed altri ancora.
Parliamo del progetto Nodes, che può essere integrato con i
classici package manager Maven:

<dependency>
  <groupId>io.aexp.nodes.graphql</groupId>
  <artifactId>nodes</artifactId>
  <version>latest</version>
</dependency>

e Gradle:

compile 'io.aexp.nodes.graphql:nodes:latest'

Approccio all'uso di Nodes

La prima incombenza che la libreria affronta è la conversione tra tipi di dato JVM e GraphQL. Esiste una corrispondenza diretta tra i tipi di dato di GraphQL Int, Float, String e Boolean e, rispettivamente, le classi wrapper di Java Integer, Float, String e Boolean.

Altro aspetto da notare subito è che esistono alcune classi centrali nella gestione del dialogo con il servizio GraphQL:

  • GraphQLTemplate, che predisporrà un template per l'interazione con il servizio GraphQL;
  • GraphQLRequestEntity, per creare la struttura di una richiesta. Riceverà l'indirizzo da contattare, eventuali argomenti o la query direttamente in formato testuale, nonché l'indicazione della classe in cui convertire la risposta;
  • GraphQLResponseEntity, per interpretare e conservare i dati della risposta.

Tali classi permettono di eseguire sia query che mutation, ciò che farà la differenza sarà solo il metodo di GraphQLTemplate che
invocheremo: query nel primo caso, mutate nel secondo.

Eseguire query

Iniziamo a sperimentare questa libreria utilizzando il servizio di prova (una banca dati per proverbi) che abbiamo realizzato in precedenza lanciandolo all'indirizzo http://localhost:8888/proverbi.
Vogliamo eseguire la query che permette di ottenere un proverbio casuale dalla banca dati:

query { proverbioRandom }

Ci aspetteremo di ottenere un risultato di questo genere:

{
  "data": {
    "proverbioRandom": "Una mela al giorno toglie il medico di torno"
  }
}

Per prima cosa realizziamo una classe che ne raccoglierà il risultato:

class ProverbioCasuale {
    private String proverbioRandom;
    public String getProverbioRandom() {
        return proverbioRandom;
    }
    public void setProverbioRandom(String proverbioRandom) {
        this.proverbioRandom = proverbioRandom;
    }
}

L'unico membro di tale classe riceverà la proprietà della risposta GraphQL che include il risultato.

Ecco come le utilizziamo le classi summenzionate per richiedere un proverbio casuale:

// definizione del template
GraphQLTemplate graphQLTemplate = new GraphQLTemplate();
// compilazione della richiesta
GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
	.url("http://localhost:8888/proverbi")
	.request(ProverbioCasuale.class)
	.build();
// ricezione della risposta
GraphQLResponseEntity<ProverbioCasuale> responseEntity = graphQLTemplate.query(requestEntity, ProverbioCasuale.class);

La risposta sarà convertita in un oggetto di classe ProverbioCasuale, che potrà essere ottenuta con il metodo getResponse invocato su
responseEntity:

// restituisce il proverbio casuale ottenuto
responseEntity.getResponse().getProverbioRandom()

Da requestEntity si potrà invocare getRequest, ovvero la richiesta in formato testuale. Si potranno creare classi per la risposta più articolate, come quella che permetterà di richiedere lo stato attuale del servizio composto dall'ultimo proverbio casuale prodotto ed il numero di richieste raccolte:

query { stato {
  ultimo
  accessi
} }

Il risultato potrebbe essere di questo tipo:

{
  "data": {
    "stato": {
      "ultimo": "Una mela al giorno toglie il medico di torno",
      "accessi": 12
    }
  }
}

La classe model richiede due variabili d'istanza ed i necessari getter e setter:

@GraphQLProperty(name="stato")
class StatoDelServizio{
	private String ultimo;
	private int accessi;
	public String getUltimo() {
		return ultimo;
	}
	public void setUltimo(String ultimo) {
		this.ultimo = ultimo;
	}
	public int getAccessi() {
		return accessi;
	}
	public void setAccessi(int accessi) {
		this.accessi = accessi;
	}
}

Si noti che con l'annotation @GraphQLProperty abbiamo specificato il nome della proprietà all'interno della query GraphQL. Ecco un esempio di utilizzo:

// definizione del template
GraphQLTemplate graphQLTemplate = new GraphQLTemplate();
// compilazione della richiesta
GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
				.url("http://localhost:8888/proverbi")
				.request(StatoDelServizio.class)
				.build();
// conversione della risposta
GraphQLResponseEntity<StatoDelServizio> responseEntity = graphQLTemplate.query(requestEntity, StatoDelServizio.class);
// stampa dei risultati
// stampa l'ultimo proverbio "Una mela al giorno toglie il medico di torno"
System.out.println(responseEntity.getResponse().getUltimo());
// stampa il numero di accessi: 12
System.out.println(responseEntity.getResponse().getAccessi());

Se si preferisce, si può usare il metodo request per fornire una richiesta con dichiarazione esplicita. Vediamolo nel seguente esempio.
Creiamo una classe per la raccolta di un certo numero di proverbi da selezionare:

class QueryProverbi{
	private String[] proverbi;
	public String[] getProverbi() {
		return proverbi;
	}
	public void setProverbi(String[] proverbi) {
		this.proverbi = proverbi;
	}
}

Eseguiamo ora la richiesta direttamente passando la query GraphQL:

// definizione del template
GraphQLTemplate graphQLTemplate = new GraphQLTemplate();
// compilazione della richiesta di tre proverbi
GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
	.url("http://localhost:8888/proverbi")
	.request("query { proverbi (quanti:3) }")
	.build();
// ricezione della risposta
GraphQLResponseEntity<QueryProverbi>> responseEntity = graphQLTemplate.query(requestEntity, QueryProverbi.class);
// stampa del numero di proverbi ottenuto nell'array
System.out.println(responseEntity.getResponse().getProverbi().length);

Esecuzione delle mutation

Per eseguire una mutation, potremo seguire il medesimo modus operandi visto sinora. Nel nostro servizio di prova, ne è prevista una per l'inserimento di un nuovo
proverbio nella banca dati:

mutation {
	nuovo(nuovo: "Chi trova un amico trova un tesoro")
}

Essa restituisce il numero aggiornato di frasi contenute nel sistema:

{
  "data": {
    "nuovo": 23
  }
}

La classe che modella il risultato è questa:

class Inserimento{
	private int nuovo;
	public int getNuovo() {
		return nuovo;
	}
	public void setNuovo(int nuovo) {
		this.nuovo = nuovo;
	}
}

Come anticipato, il suo impiego in una mutation non porterà grandi differenze rispetto alle query, ma solo l'uso del metodo mutate al posto
di query.

// definizione del template
GraphQLTemplate graphQLTemplate = new GraphQLTemplate();
// richiesta per l'inserimento di un nuovo proverbio
GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
				  .url("http://localhost:8888/proverbi")
				  .request("mutation{ nuovo(nuovo:\"Chi trova un amico trova un tesoro\")}")
				  .build();
// esecuzione della richiesta
GraphQLResponseEntity responseEntity = graphQLTemplate.mutate(requestEntity, Inserimento.class);
// stampa il numero aggiornato di proverbi presenti nel sistema
System.out.println(responseEntity.getResponse().getNuovo());

Ti consigliamo anche