Integración sin esfuerzo de APIs RESTful y GraphQL con Spring Boot para servicios flexibles

Introducción

En el ecosistema empresarial moderno, las APIs son una parte fundamental de la arquitectura de software. Las arquitecturas flexibles requieren que integremos múltiples tipos de APIs, como RESTful y GraphQL, para satisfacer diversas necesidades. Este artículo abordará cómo implementar y combinar ambos tipos de APIs en un solo proyecto de Spring Boot, permitiendo crear servicios más versátiles.

Prerrequisitos y configuración

Asegúrate de tener el siguiente entorno configurado:

  • Java 11 o superior
  • Spring Boot 3.x
  • Dependencias de Web, JPA y GraphQL

Configura tu proyecto pom.xml o build.gradle con las siguientes dependencias:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>com.graphql-java-kickstart</groupId>
  <artifactId>graphql-spring-boot-starter</artifactId>
</dependency>

Implementación paso a paso

Creación de un API RESTful

Primero, implementemos un simple controlador REST para gestionar entidades Product.

@RestController
@RequestMapping("/api/products")
public class ProductController {
    @Autowired
    private ProductService productService;

    @GetMapping
    public List<Product> getAllProducts() {
        return productService.findAll();
    }

    @PostMapping
    public Product createProduct(@RequestBody Product product) {
        return productService.save(product);
    }
}

Implementación de GraphQL

A continuación, definimos un endpoint GraphQL para la misma entidad Product.

@Component
public class ProductGraphQLResolver implements GraphQLQueryResolver, GraphQLMutationResolver {
    @Autowired
    private ProductService productService;

    public List<Product> allProducts() {
        return productService.findAll();
    }

    public Product createProduct(ProductInput input) {
        return productService.save(input.toProduct());
    }
}

Definimos el esquema GraphQL en un archivo schema.graphqls:

type Query {
  allProducts: [Product]
}

type Mutation {
  createProduct(product: ProductInput): Product
}

type Product {
  id: ID
  name: String
  price: Float
}

input ProductInput {
  name: String
  price: Float
}

Mejores prácticas y patrones

  • Utilizar capas de servicio para la lógica de negocio para desacoplar controladores de la lógica empresarial.
  • Implementar DTO y Mappers para transformar entidades a respuestas API y viceversa.

Tests y validación

Implementa pruebas unitarias y de integración utilizando el framework JUnit y Spring Boot Test para asegurar la funcionalidad de ambos tipos de APIs.

@SpringBootTest
public class ProductControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void getAllProducts_ReturnsProductList() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/api/products"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", hasSize(greaterThan(0))));
    }
}

Consideraciones de rendimiento y seguridad

  • Utiliza caché en consultas GraphQL con DataLoader para optimizar consultas de datos relaciones.
  • Implementa seguridad con Spring Security para proteger tus endpoints con autenticación y autorización.

Conclusiones y siguientes pasos

Esta configuración inicial proporciona una base robusta para construir aplicaciones resilientes y flexibles. Considera explorar Spring Boot Actuator y GraphQL subscription para funcionalidades avanzadas.

Documentación oficial: Spring Boot, GraphQL Spring Boot.