GraphQL ha emergido como una alternativa potente y flexible a las APIs REST tradicionales, ofreciendo a los desarrolladores un mayor control sobre los datos que solicitan y reciben. En este artículo, exploraremos cómo implementar GraphQL en Scala utilizando Sangria, una popular librería GraphQL para Scala. Aprenderemos a definir esquemas, ejecutar consultas y mutaciones, y compararemos GraphQL con REST para entender mejor sus beneficios. Este artículo te guiará paso a paso para que puedas comenzar a utilizar GraphQL en tus proyectos Scala.

Introducción a GraphQL

GraphQL es un lenguaje de consulta para tu API y un tiempo de ejecución para satisfacer esas consultas con tus datos existentes. Proporciona una descripción completa y comprensible de los datos en tu API, dando a los clientes el poder de pedir exactamente lo que necesitan y nada más. GraphQL organiza la información en grafos, permitiendo a los clientes navegar entre datos relacionados de manera eficiente.

Características clave de GraphQL:

  • Tipado Fuerte: Cada campo en un esquema GraphQL tiene un tipo específico, lo que permite la validación en tiempo de compilación y ayuda a prevenir errores en tiempo de ejecución.
  • Introspección: Los clientes pueden consultar el esquema de la API para descubrir qué datos están disponibles y cómo están relacionados.
  • Consultas Precisas: Los clientes especifican exactamente qué datos necesitan, evitando la sobre-recuperación de datos (over-fetching) común en las APIs REST.
  • Múltiples Recursos en una Solicitud: GraphQL permite a los clientes solicitar datos de múltiples recursos en una sola solicitud, reduciendo el número de viajes de ida y vuelta al servidor.

Ejemplo básico de una consulta GraphQL:


query {
  user(id: "123") {
    id
    name
    email
  }
}

Esta consulta pide el id, name, y email del usuario con id «123».

Definición de esquemas en Sangria

Sangria es una implementación de GraphQL en Scala que proporciona las herramientas necesarias para construir APIs GraphQL robustas y eficientes. La definición de esquemas en Sangria es un paso fundamental para exponer tus datos a través de GraphQL.

Para empezar, necesitas definir los tipos de datos que estarán disponibles en tu API. Aquí hay un ejemplo de cómo definir un tipo User en Sangria:


import sangria.schema._

object Types {
  val UserType = ObjectType(
    "User",
    fields[Unit, User](
      Field("id", StringType, resolve = _.value.id),
      Field("name", StringType, resolve = _.value.name),
      Field("email", StringType, resolve = _.value.email)
    )
  )
}

En este código:

  • Importamos sangria.schema._ para acceder a las definiciones de esquema.
  • Definimos un ObjectType llamado UserType.
  • Especificamos los campos del tipo User: id, name, y email, junto con las funciones de resolución que indican cómo obtener los valores de estos campos.

A continuación, necesitas definir la consulta raíz (QueryType) que será el punto de entrada para todas las consultas GraphQL:


import sangria.macros.derive._

object Query {
  val QueryType = ObjectType(
    "Query",
    fields[MyContext, Unit](
      Field("user", OptionType(Types.UserType), arguments = Argument("id", StringType) :: Nil, resolve = c => ctx.dao.getUser(c.arg[String]("id")))
    )
  )
}

En este código:

  • Definimos un ObjectType llamado QueryType.
  • Añadimos un campo user que acepta un argumento id de tipo StringType.
  • La función de resolución utiliza el argumento id para obtener un usuario de un DAO (Data Access Object) llamado ctx.dao.getUser.

Finalmente, combinas los tipos y la consulta raíz para crear el esquema GraphQL:


import sangria.schema.Schema

object GraphQLSchema {
  val schema = Schema(Query.QueryType)
}

Este esquema se utilizará para procesar las consultas GraphQL entrantes.

Consultas y mutaciones en GraphQL

Una vez que tienes tu esquema GraphQL definido en Sangria, puedes empezar a ejecutar consultas y mutaciones para interactuar con tus datos. Las consultas se utilizan para leer datos, mientras que las mutaciones se utilizan para modificar datos.

Ejemplo de una consulta GraphQL:


query GetUser {
  user(id: "123") {
    id
    name
    email
  }
}

Para ejecutar esta consulta en Sangria, puedes utilizar el siguiente código:


import sangria.execution.Executor
import sangria.parser.QueryParser
import scala.concurrent.ExecutionContext.Implicits.global

val query = """
  query GetUser {
    user(id: \"123\") {
      id
      name
      email
    }
  }
  """

QueryParser.parse(query) match {
  case Success(queryAst) =>
    Executor.execute(
      GraphQLSchema.schema,
      queryAst,
      MyContext()
    ).map(result => println(result))
  case Failure(error) =>
    println(error)
}

En este código:

  • Parseamos la consulta GraphQL utilizando QueryParser.parse.
  • Ejecutamos la consulta utilizando Executor.execute, pasando el esquema, el AST de la consulta, y un contexto (MyContext) que contiene los DAOs necesarios.
  • Imprimimos el resultado de la consulta.

Ejemplo de una mutación GraphQL:


mutation UpdateUser {
  updateUser(id: "123", name: "New Name") {
    id
    name
    email
  }
}

Para ejecutar esta mutación en Sangria, primero debes definir el tipo de mutación en tu esquema:


val MutationType = ObjectType(
  "Mutation",
  fields[MyContext, Unit](
    Field("updateUser", OptionType(Types.UserType), arguments = Argument("id", StringType) :: Argument("name", StringType) :: Nil, resolve = c => ctx.dao.updateUser(c.arg[String]("id"), c.arg[String]("name")))
  )
)

val schema = Schema(Query.QueryType, Some(MutationType))

Luego, puedes ejecutar la mutación de manera similar a la consulta:


import sangria.execution.Executor
import sangria.parser.QueryParser
import scala.concurrent.ExecutionContext.Implicits.global

val mutation = """
  mutation UpdateUser {
    updateUser(id: \"123\", name: \"New Name\") {
      id
      name
      email
    }
  }
  """

QueryParser.parse(mutation) match {
  case Success(mutationAst) =>
    Executor.execute(
      GraphQLSchema.schema,
      mutationAst,
      MyContext()
    ).map(result => println(result))
  case Failure(error) =>
    println(error)
}

Este código actualiza el nombre del usuario con id «123» a «New Name» y luego imprime los datos actualizados del usuario.

Comparación con REST y beneficios

REST (Representational State Transfer) ha sido el estándar de facto para la construcción de APIs durante muchos años. Sin embargo, GraphQL ofrece varias ventajas sobre REST, especialmente en términos de flexibilidad y eficiencia.

Principales diferencias entre GraphQL y REST:

  • Sobre-recuperación vs. Recuperación Precisa: En REST, los endpoints a menudo devuelven más datos de los que el cliente necesita (sobre-recuperación). GraphQL permite a los clientes especificar exactamente qué datos necesitan, evitando la sobre-recuperación.
  • Múltiples Solicitudes vs. Una Sola Solicitud: Para obtener datos de múltiples recursos en REST, a menudo se necesitan múltiples solicitudes al servidor. GraphQL permite a los clientes solicitar datos de múltiples recursos en una sola solicitud.
  • Tipado Fuerte vs. Tipado Débil: GraphQL utiliza un esquema tipado fuertemente, lo que permite la validación en tiempo de compilación y ayuda a prevenir errores en tiempo de ejecución. REST, por otro lado, a menudo utiliza formatos de datos sin tipado fuerte como JSON.

Beneficios de usar GraphQL:

  • Eficiencia: GraphQL reduce la cantidad de datos transferidos entre el cliente y el servidor, lo que puede mejorar el rendimiento de las aplicaciones, especialmente en dispositivos móviles con conexiones de red limitadas.
  • Flexibilidad: GraphQL permite a los clientes solicitar exactamente los datos que necesitan, lo que facilita la adaptación de la API a diferentes casos de uso.
  • Productividad del Desarrollador: GraphQL proporciona herramientas como la introspección y la validación en tiempo de compilación, lo que puede mejorar la productividad del desarrollador y reducir los errores.
  • Evolución de la API: GraphQL facilita la evolución de la API al permitir a los desarrolladores añadir nuevos campos y tipos sin afectar a los clientes existentes.

En resumen, GraphQL ofrece una alternativa más flexible y eficiente a REST, permitiendo a los desarrolladores construir APIs más robustas y adaptables.

 

En este artículo, hemos explorado cómo implementar GraphQL en Scala utilizando Sangria. Hemos aprendido a definir esquemas, ejecutar consultas y mutaciones, y comparar GraphQL con REST. GraphQL ofrece una alternativa poderosa y flexible a las APIs REST tradicionales, proporcionando a los desarrolladores un mayor control sobre los datos que solicitan y reciben. Con Sangria, puedes construir APIs GraphQL robustas y eficientes en Scala, aprovechando las ventajas de la tipificación estática y la concurrencia de Scala. Considera la posibilidad de utilizar GraphQL en tus próximos proyectos para mejorar la eficiencia y flexibilidad de tus APIs.

Ads Blocker Image Powered by Code Help Pro

Por favor, permite que se muestren anuncios en nuestro sitio web

Querido lector,

Esperamos que estés disfrutando de nuestro contenido. Entendemos la importancia de la experiencia sin interrupciones, pero también queremos asegurarnos de que podamos seguir brindándote contenido de alta calidad de forma gratuita. Desactivar tu bloqueador de anuncios en nuestro sitio nos ayuda enormemente a lograrlo.

¡Gracias por tu comprensión y apoyo!