MicroProfile GraphQL acaba de lanzar su primera versión (1.0). En esta publicación de blog, exploraremos algunas de las funcionalidades disponibles en esta versión.
Haremos referencia a una aplicación de ejemplo, donde usamos Thorntail como tiempo de ejecución, agregando manualmente la implementación de SmallRye GraphQL .
¿Qué es GraphQL?
“GraphQL es un lenguaje de manipulación y consulta de datos de código abierto para API, y un tiempo de ejecución para completar consultas con datos existentes. GraphQL interpreta cadenas del cliente y devuelve datos de una manera predefinida, predecible y comprensible. GraphQL es una alternativa, aunque no necesariamente un reemplazo de REST ".
Lea la especificación GraphQL completa
¿Qué es MicroProfile GraphQL?
“La intención de la especificación MicroProfile GraphQL es proporcionar un conjunto de API de" código primero "que permitirá a los usuarios desarrollar rápidamente aplicaciones portátiles basadas en GraphQL en Java. Hay 2 requisitos principales para todas las implementaciones de esta especificación, a saber:
- Genere y ponga a disposición el esquema GraphQL. Esto se hace mirando las anotaciones en el código de los usuarios y debe incluir todas las consultas y mutaciones de GraphQL, así como todas las entidades definidas implícitamente a través del tipo de respuesta o argumento (s) de consultas y mutaciones.
- Ejecute solicitudes GraphQL. Esto tendrá la forma de una consulta o una mutación. Como mínimo, la especificación debe admitir la ejecución de estas solicitudes a través de HTTP ".
Lea la especificación completa de MicroProfile GraphQL
El ejemplo
Haremos referencia a un ejemplo a lo largo de esta publicación en el que tenemos un sistema que puntúa a las personas en función de algunas actividades que realizan.
- Qué tan en forma están, ejemplo con qué frecuencia van al gimnasio
- Qué tan seguros conducen, sin exceder el límite de velocidad, etc.
- Cuántos pasos dan al día, etc.
Tenemos un objeto Persona que contiene todos los detalles sobre la persona (nombre, apellido, dirección, teléfono, redes sociales, etc.) y tenemos un objeto de puntuación que contiene la puntuación de una determinada acción.
Consultar datos
En GraphQL, es similar a REST . Una consulta no cambia datos, solo recibe datos. La diferencia es que con GraphQL puedes preguntar lo que quieras.
Usando JAX-RS
Digamos que quieres información sobre una persona, en JAX-RS crearíamos algo como esto:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | @Path ( "/person" ) @Consumes (MediaType.APPLICATION_JSON) @Produces (MediaType.APPLICATION_JSON) @Tag (name = "Person service" ,description = "Person Services" ) public class PersonRestApi { @Inject private PersonDB personDB; @GET @Path ( "/{id}" ) @Operation (description = "Get a person using the person's Id" ) public Response getPerson( @PathParam ( "id" ) int id){ return Response.ok(personDB.getPerson(id)).build(); } } |
NOTA: Para documentar el punto final, también necesita MicroProfile OpenAPI ( y ).
Puede obtener el esquema en , que describirá los servicios y modelos disponibles.
Hacer un GET en devolverá la Persona en formato json.
Dependiendo del tamaño de Person, este puede ser un archivo grande:
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | { "addresses" : [ { "code" : "49512-5971" , "lines" : [ "212 Neomi Ridges" , "Lake Winfordview" , "Wisconsin" , "Myanmar" ] }, { "code" : "09444-8413" , "lines" : [ "1443 Bogan Harbor" , "East Jacinto" , "New York" , "Timor-Leste" ] } ], "biography" : "Perferendis asperiores non. Cumque voluptas et nisi rerum tenetur quaerat. Doloribus nihil et. Autem autem sapiente et ut inventore ipsum sint. Aut error pariatur quidem itaque deserunt. Dolorum aspernatur exercitationem. In tenetur quia iste qui quia officiis." , "birthDate" : "25/01/1967" , "coverphotos" : [ ], "creditCards" : [ { "expiry" : "2013-9-12" , "number" : "1234-2121-1221-1211" , "type" : "solo" } ], "emailAddresses" : [ "leo.lesch@gmail.com" , "laurie.ankunding@gmail.com" ], "favColor" : "lime" , "gender" : "Female" , "id" : 1, "idNumber" : "334-58-1049" , "imClients" : [ { "identifier" : "Slack" , "im" : "cory.langworth" }, { "identifier" : "ICQ" , "im" : "booker.boyle" } ], "interests" : [ "PUBG" , "meditation" ], "joinDate" : "14/09/2019" , "locale" : "en-ZA" , "maritalStatus" : "Divorced" , "names" : [ "Nicholas" , "Edwin" ], "nicknames" : [ "Oscar Ruitt" ], "occupation" : "Officer" , "organization" : "Hodkiewicz Group" , "phoneNumbers" : [ { "number" : "1-852-821-3630" , "type" : "Cell" }, { "number" : "783.874.6411" , "type" : "Home" }, { "number" : "(489) 031-5336 x8428" , "type" : "Work" } ], "profilePictures" : [ ], "relations" : [ { "personURI" : "/rest/person/46" , "relationType" : "Spouse" } ], "skills" : [ "Communication" , "Confidence" ], "socialMedias" : [ { "name" : "@jordan.hane" , "username" : "Twitter" }, { "name" : "annamarie.casper" , "username" : "Facebook" } ], "surname" : "Zulauf" , "taglines" : [ "You will find only what you bring in." , "Chuck Norris' keyboard doesn't have a F1 key, the computer asks him for help." ], "title" : "Dr." , "userAgent" : "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1" , "username" : "trent.kub" , } |
Ahora bien, si está creando una aplicación móvil, o incluso si la consume de otro servicio, es posible que solo le importe el , y como ejemplo, pero está recuperando una gran cantidad de datos. Ahora necesita filtrar toda la información irrelevante (para usted).
Usando MicroProfile GraphQL
Ahora agreguemos MicroProfile GraphQL a esto y veamos cómo podemos consultar los datos:
Primero agregue esto a su pom.xml (al menos hasta que el tiempo de ejecución lo admita como una funcionalidad lista para usar):
1 2 3 4 5 | < dependency > < groupId >io.smallrye</ groupId > < artifactId >smallrye-graphql-servlet</ artifactId > < version >1.0.0</ version > </ dependency > |
Ahora podemos agregar un punto final GraphQL (similar a nuestro servicio REST anterior)
01 02 03 04 05 06 07 08 09 10 11 12 | @GraphQLApi public class ProfileGraphQLApi { @Inject private PersonDB personDB; @Query @Description ( "Get a person using the person's Id" ) public Person getPerson( @Name ( "personId" ) int personId){ return personDB.getPerson(personId); } } |
Como puede ver, el código es exactamente el mismo que el del servicio REST, pero tenemos algunas anotaciones nuevas:
- esto le dice al tiempo de ejecución que este es un punto final GraphQL, y todos los métodos anotados con y serán expuestos.
- este es un método consultable.
Ahora puede realizar una consulta a . Usemos el mismo ejemplo anterior, desea obtener el , y de la persona:
1 2 3 4 5 6 7 | { person(personId:1){ names surname idNumber } } |
Esto devolverá exactamente lo que solicitó:
01 02 03 04 05 06 07 08 09 10 11 12 | { "data" : { "person" : { "names" : [ "Nicholas" , "Edwin" ], "surname" : "Zulauf" , "idNumber" : "334-58-1049" } } } |
y como puede ver, la carga útil es mucho menor que en el ejemplo REST.
Acabamos de resolver el problema de la búsqueda excesiva:
"Recuperar en exceso es obtener demasiados datos, por lo que hay datos en la respuesta que no usa".
Ahora digamos que también queremos obtener las puntuaciones de esta persona. En el ejemplo de REST, necesitamos obtener el de nuestro enorme json original y luego realizar una llamada posterior al servicio de puntuación:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 dieciséis | { @ApplicationScoped @Path ( "/score" ) @Consumes (MediaType.APPLICATION_JSON) @Produces
|