ABONAMENTE VIDEO REDACȚIA
RO
EN
×
▼ LISTĂ EDIȚII ▼
Numărul 100
Abonament PDF

GraphQL - Un alt mod de a dezvolta API-uri în Java

Horia Hermeneanu
Java Software Engineer @ NTT DATA Romania
PROGRAMARE


Utilizarea API-urilor a cunoscut o creștere extraordinară. Pe măsură ce aplicațiile mobile și web au devenit mai populare, a existat o nevoie evidentă de a deconecta backendul aplicației de la front-end. Adevărul este că API-urile sunt acum prezente în majoritatea software-urilor dezvoltate în zilele noastre. Această utilizare pe scară largă a API-urilor a arătat, de asemenea, câteva dezavantaje ale modului în care API-urile au fost construite și consumate, ceea ce a generat inovații precum REST și GraphQL. În cadrul companiei noastre avem proiecte cu GraphQL, unde implementarea a avut succes și nu au fost showstoppers din punct de vedere tehnic.

GraphQL este, într-adevăr, tehnologia care a atras atenția comunității de developeri din acest moment. Unii dezvoltatori chiar o descriu ca fiind "a better Rest". De ce? Câteva dintre argumentele principale ar fi: un singur request pentru a aduce date de pe server comparativ cu requesturi separate pentru fiecare resursă; un singur endpoint pentru toate requesturile comparativ cu fiecare resursă având endpointul propriu, plus multe altele pe care le vom aborda puțin mai târziu.

Aceste argumente stau la baza GraphQL-ului, care a devenit un standard pentru dezvoltarea de API și care a câștigat încrederea din ce în ce mai multor developeri.

În ultimii ani, GraphQL a dovedit că își menține puterea, proiectele, produsele și serviciile, crescând pentru a forma un ecosistem în jurul său.

Figura 1. Evoluția GraphQL . Sursa: Google Trends

Pe scurt, ce este GraphQL?

Definiția ca la carte spune că GraphQL este o specificație a unui limbaj pentru API-uri, prin care poți să interoghezi și să manipulezi date.

Principalul concept care stă la baza GraphQL este faptul că descrie datele disponibile prin intermediul unei scheme. În consecință, consumatorul de API poate cere exact ceea ce are nevoie. Mai multe informații despre nomenclatura GraphQL, puțin mai jos.

A fost conceput de Facebook în anul 2012, dar a fost făcut public doar din 2015, iar prima versiune stabilă a ieșit pe piața doar în iunie 2018.

Este open-source dezvoltat cu JavaScript, Ruby, Scala și din ce în ce mai multe companii au început să îl utilizeze în dezvoltarea de produse software.

Cum funcționează GraphQL

Pentru a înțelege mai bine conceptele GraphQL, mai jos, sunt explicate câteva dintre cuvintele cheie:

Un server GraphQL oferă unui client o schemă predefinită - un model al datelor care pot fi solicitate de la server. Cu alte cuvinte, schema servește ca un punct de mijloc între client și server în timp ce definește modul de accesare a datelor.

Figura 2. Schema generală a arhitecturii de GraphQL

GraphQL în lumea Java

Prima dată când Facebook a vorbit public despre GraphQL a fost la React.js Conf 2015. Deoarece Facebook obișnuia să vorbească întotdeauna despre GraphQL în contextul React, a durat ceva timp ca developerii non-React să înțeleagă că GraphQL nu este în niciun caz o tehnologie care se limitează la utilizarea cu React.

GraphQL este un limbaj de programare agnostic și există diferite implementări în multe limbaje (Java, C#, PHP, Scala, etc).

În acest articol ne axăm mai mult pe limbajul Java, deci alegerea firească de implementare este graphql-java. Este posibil să nu fie singura implementare Java, dar este cu siguranță cea mai folosită și matură în acest moment. Acest proiect de bază, graphql-java, rămâne fidel specificațiilor, dar există o serie de alte proiecte de sprijin pentru a facilita integrarea și utilizarea acestuia. Mai multe detalii despre celelalte proiecte, se găsesc aici.

Cele mai folosite și utile tool-uri în development

În GraphQL, trebuie declarată schema de date, astfel încât consumatorii de API să poată introspecta sistemul și să interogheze corect datele. Cu toate acestea, schema trebuie să fie o reprezentare exactă a claselor de date. Deși s-ar putea crea ambele lucruri manual, generarea uneia din cealaltă va reduce efortul și erorile. O abordare este definirea schemei și generarea claselor de date pe baza schemei. Această abordare este furnizată de graphql-apigen și graphql-java-tools.

Cu toate că această abordare ar putea fi foarte utilă dacă este un proiect nou cu o specificație strictă a schemei, ce se poate face când avem deja clasele definite? Pentru a rezolva această situație, există un proiect numit graphql-java-annotations care se bazează pe această abordare. Totuși, dezvoltarea acestuia pare să se fi oprit și comunitatea pare să se îndrepte spre graphgql-spqr (pronunțat "speaker"). Se pare că aceasta va deveni abordarea oficială a clasei graphql-java.

Pentru a evidenția mai bine cum se folosesc aceste librării, vom construi un mic exemplu cu Spring Boot, Hibernate(Mysql) și Maven. Astfel, se adaugă dependințele de GraphQL în pom.xml:

După ce se construiesc entitățile și clasele de repository, următorul pas ar fi definirea schemei în folderul de resources, într-un fişier(e) cu extensia ". graphqls":

type Vehicle {
  id: ID!, 
  type: String, 
  modelCode: String, 
  brandName: String, 
  launchDate: String
}
type Query {
  vehicles(count: Int): [Vehicle] 
  vehicle(id: ID):Vehicle
}

type Mutation {
  createVehicle(type: String!, 
                modelCode: String!, 
        brandName: String, 
                launchDate: String):Vehicle

Obiectele de query sau mutation nu au nicio clasă de date asociată. De aceea, este nevoie de clasele Resolver care implementează GraphQLQueryResolver /GraphQLMutationResolver:

package com.demo.graphql.mutation; 

import org.springframework.beans.factory
  .annotation.Autowired;
import org.springframework.stereotype.Component; 
import com.coxautodev.graphql
  .tools.GraphQLMutationResolver; 
import com.demo.graphql.dao.entity.Vehicle; 
import com.demo.graphql.service.VehicleService; 

@Component 
public class VehicleMutation implements 
  GraphQLMutationResolver {
  @Autowired 
  private VehicleService vehicleService; 

  public Vehicle createVehicle(final String type, 
    final String modelCode, final String brandName){

  return this.vehicleService.createVehicle(type,
    modelCode, brandName, launchDate);
  }
}

și

package com.demo.graphql.query; 

...
@Component 
public class VehicleQuery 
  implements GraphQLQueryResolver {

  @Autowired 
  private VehicleService vehicleService; 

  public List getVehicles(final int count) {
    return this.vehicleService.getAllVehicles(count);
  }

  public Optional getVehicle(final int id) {
    return this.vehicleService.getVehicle(id);
  }
}

Se poate observa că semnăturile metodelor din clasele Resolver pentru query și mutation au fost declarate și în schema de mai sus. Pentru mai multe detalii despre implementarea mini exemplului, găsiți pe GitHub.

Cum să testezi API-ul?

În partea de testare și debugging a API-ului, GraphQL vine în ajutorul developerilor și oferă un mediu de dezvoltare integrat (IDE) care maximizează productivitatea.

Cei de la GraphQL se axează mult pe partea de web. Ca urmare, alegerea lor firească pentru un IDE este rularea lui în browser care permite vizualizarea schemei, scrierea de queries/mutations și afișarea rezultatelor. Sunt câteva implementări precum: GraphQL Playground, GraphQL IDE dar cea mai folosită implementare se numește GraphiQL.

Bineînțeles că sunt și alte opțiuni care pot fi luate în calcul: curl, wget, tool-uri(Postman) care reduc "the boilerplate" și îmbunătățesc portabilitatea, dar ignoră semantica datelor. De exemplu, dacă se trimite un tip greșit de argument sau doar pentru verificarea de ce opțiuni sunt disponibile, trebuie să vă bazați pe API pentru a fi descriptiv și util. Toate aceste probleme sunt rezolvate de GraphiQL pentru că acceptă debugging as-you-type, oferind sugestii și subliniind erorile. Totodată, GraphiQL vine cu un vizualizator JSON cu toate caracteristicile aferente: pliere cod, indentare automată etc.

După rularea mini exemplului nostru cu Spring, se poate accesa graphiQL la calea: http://localhost:8080/graphiql și va redirecta userul către interfața unde se pot rula queries, mutations și introspecta schema.

Ca orice din lumea tehnică, și GraphQL are parți pozitive dar și parți negative. Cum mulți spun că GraphQL ar putea fi sfârșitul lui Rest, pentru a putea evidenția mai bine punctele forte și cele slabe ale GraphQL-ului, în rândurile următoare expunem o mică analiză comparativă a celor două.

GraphQL vs. Rest. Aspecte pozitive și negative

Deoarece ambele sunt specificații pentru construirea și consumarea API-urilor, GraphQL și REST au lucruri în comun. Ambii recuperează resurse prin trimiterea de interogări, pot returna date JSON și pot fi operați prin HTTP.

În plus, vom vorbi despre diferența GraphQL vs.REST și despre modul în care schimbă experiența dezvoltatorului de a construi și consuma un API.

Aspecte pozitive

Soluția perfectă pentru sisteme complexe și microservicii. Prin integrarea mai multor sisteme în spatele API-ului său, GraphQL le unifică și le ascunde complexitatea. Serverul GraphQL este apoi responsabil pentru preluarea datelor din sistemele existente și împachetarea acestora în formatul de răspuns GraphQL. Acest lucru ajută foarte mult când infrastructurile vechi sau API-urile terțe care s-au extins de-a lungul anilor și mentenanța lor sunt destul de dificile.

O altă situație în care se pretează soluția cu GraphQL ar fi migrarea de la o aplicație backend monolitică la o arhitectură de microservicii. Un API GraphQL poate ajuta la gestionarea comunicării între mai multe microservicii prin fuzionarea acestora într-o singură schemă GraphQL. În timp ce fiecare microserviciu își definește propria schemă GraphQL și are propriul punct final GraphQL, un gateway API GraphQL consolidează toate schemele într-o singură schemă globală.

Validarea automată a datelor. Funcția de introspecție a GraphQL permite navigarea în types și descoperirea schemei pentru a se asigura că aplicațiile cer doar ceea ce este posibil și în formatul dictat de schemă. Astfel, se poate interoga schema și se poate observa cum sunt configurate datele acolo. Pe baza acestora, se pot adăuga cu ușurință câmpuri noi la interogările existente printr-un IDE GraphQL.

Figura 4. Gateway API GraphQL. Sursa: How to GraphQL

Versionarea API-ului. Dezvoltarea API implică o problemă de a păstra vechea versiune până când dezvoltatorii fac trecerea la cea nouă. Prin urmare, cu REST este obișnuit să oferiți mai multe versiuni API. Cu toate acestea, GraphQL elimină necesitatea versionării prin deprecated API la nivel de câmp. Câmpurile deprecated pot fi ulterior eliminate din schemă fără a afecta queries existente. GraphQL permite acest lucru prin crearea unui API uniform pe întreaga aplicație care nu este limitat de un anumit motor de stocare.

Code sharing. În GraphQL, câmpurile utilizate în mai multe queries pot fi partajate la un nivel mai ridicat de componentă pentru reutilizare. Acest lucru se poate realiza prin intermediul unei caracteristici GraphQL numită fragments. Astfel, se pot obține date diferite păstrând același field schema.

Aspecte neutre

Mesaje de eroare. GraphQL pune accent pe consistență și predictibilitate și, pe acel ton, răspunsul de la un server GraphQL are întotdeauna o structură previzibilă, constând din cele 3 câmpuri:

Orice server GraphQL va gestiona automat erorile sintactice și de validare și va informa clientul în mod corespunzător, dar excepțiile întâlnite în funcțiile de rezolvare necesită de obicei o manipulare specifică aplicației. Gestionarea erorilor poate fi personalizată la câteva niveluri diferite.

La cel mai înalt nivel, graphql-java-servlet expune o metodă (numită isClientError) care decide dacă mesajul unei erori va fi trimis clientului textual sau dacă va fi ascuns de un mesaj de eroare generic al serverului. În mod implicit, numai erorile sintactice și de validare vor fi trimise așa cum sunt. Aceasta este o valoare implicită rezonabilă, deoarece mesajele de excepție pot dezvălui o mulțime de informații care, în mod normal, ar trebui ascunse vizualizării publice. Cu toate acestea, mesajele de eroare neinformative (sau chiar prea multe mesaje) pot avea un impact negativ sever asupra utilizabilității API-ului.

Figura 5. Structura Response - Eroare aruncata de GraphQL server backend

Un răspuns GraphQL are întotdeauna statusul HTTP 200 OK.

Codurile de eroare HTTP nu sunt relevante atunci când se utilizează GraphQL deoarece, dacă o solicitare eșuează, sarcina utilă JSON a răspunsului serverului va conține un câmp rădăcină numit "errors" care adună informații precise despre problemele apărute pe partea serverului. Mai mult, deoarece GraphQL permite trimiterea mai multor operațiuni în aceeași solicitare, este foarte posibil ca o cerere să nu reușească decât parțial și să returneze date și erori reale.

Aspecte negative

Probleme de performanță cu interogări complexe. În timp ce permite clienților să solicite exact ceea ce au nevoie, GraphQL query poate întâmpina probleme de performanță dacă un client solicită prea multe câmpuri imbricate, respectiv un response Json foarte complicat.

Suprasolicitare pentru aplicații mici. În timp ce GraphQL este soluția potrivită pentru mai multe microservicii, este mai bine să alegeți arhitectura REST în cazul unei aplicații simple. REST poate fi, de asemenea, o abordare valoroasă pentru conectarea aplicațiilor bazate pe resurse care nu au nevoie de interogările flexibile oferite de GraphQL.

Cache web. Memorarea în cache a GraphQL la baza de date sau client poate fi implementată cu clienții Apollo sau Relay care au mecanisme de cache încorporate. Cu toate acestea, GraphQL nu se bazează pe metodele de cache HTTP, care permit stocarea conținutului unei cereri. Memorarea în cache ajută la reducerea cantității de trafic către un server, păstrând informații accesate frecvent de către client.

Upload de fișiere. Deoarece GraphQL nu suportă obiecte de tip fișiere, o caracteristică de încărcare a fișierelor nu este inclusă în specificația sa. Pentru a permite încărcarea fișierelor în aplicații web cu GraphQL, există mai multe opțiuni: codificare în Base64 a conținutului de fișier sau folosirea unei biblioteci care suportă multipart request.

Când se folosește GraphQL

Cele mai potrivite scenarii pentru utilizarea GraphQL se pretează cel mai bine sunt:

Figura 6. GraphQL server - agregare de resurse multiple. Sursa: Technology Radar

Concluzie

Într-un discurs la Summitul GraphQL din 2016, Lee Byron (Executive Director, GraphQL Foundation, și GraphQL Co-Creator) a prezentat un "Master Plan secret" în care își proiectează evoluția GraphQL.

Într-o lume ideală, spunea el, adoptarea GraphQL va arăta cam așa:

În acest moment, ne aflăm pe la sfârșitul fazei companiilor mari și a giganților tehnologici - GitHub, Pinterest, Intuit, Coursera și Shopify sau alte companii, care folosesc toate, GraphQL într-un mediu sau altul.

În timp ce GraphQL s-ar putea să nu sune perfect pentru REST, acesta conține setul potrivit de ingrediente de a fi în jur pentru mult timp. Ca urmare, nu este dificil să ne imaginăm că planul de 4-5 ani pe care l-a menționat Byron se desfășoară așa cum spera, deși poate că este un pic prea ambițios din punct de vedere al omniprezenței.

De asemenea, Alan Johnson spunea într-un articol al său că GraphQL va fi noul trend în dezvoltarea de API și că în câțiva ani REST va deveni demodat: "Mark my words: in 5 years, newly minted full-stack app developers won't be debating RESTfulness anymore, because REST API design will be obsolete. "

După părerea mea, atât REST, cât și GraphQL sunt modalități eficiente de a proiecta modul în care va funcționa un API și modul în care aplicațiile vor accesa datele din acesta. Oricare dintre cele două sunt soluții excelente. Alegerea uneia dintre ele ar trebui să revină echipei de dezvoltare și să se facă în urma unui studiu de caz care să pună în balanța avantajele și dezavantajele fiecăruia dintre cele două standarde.

Referințe

  1. Eve Porcello and Alex Banks(2018). Learning GraphQL

  2. GraphQL - Official Site

  3. How to GraphQL

  4. Best Practices in GraphQL on Official Site

  5. GraphQL in Java - Official documentation

  6. Technology Radar - GraphQL

  7. Technology Radar - GraphQL for server-side resource aggregation

  8. GraphQL - Supported Programming Languages - Official Site

  9. Official Documentation Release

LANSAREA NUMĂRULUI 101

Prezentări articole și Panel:
Democratizarea machine learning în Cloud

Joi, 26 Noiembrie, ora 18:00

Înregistrează-te

Facebook Meetup Live on StreamEvent.ro

VIDEO: NUMĂRULUI 100

Sponsori

  • comply advantage
  • ntt data
  • Betfair
  • Accenture
  • Siemens
  • Bosch
  • FlowTraders
  • MHP
  • Connatix
  • Cognizant Softvision
  • BoatyardX
  • Colors in projects