Introduction à GraphQL et Kotlin
GraphQL est un langage de requête pour les API qui permet aux clients de recevoir uniquement les données dont ils ont réellement besoin. Contrairement à REST, où chaque point de terminaison renvoie une structure fixe, GraphQL offre de la flexibilité : une seule requête peut combiner des données provenant de différentes sources. Kotlin, quant à lui, est un langage moderne pour la JVM qui allie concision et sécurité de typage. Dans ce tutoriel, nous allons créer une API GraphQL complète en utilisant Kotlin et la bibliothèque graphql-kotlin-spring-server.
Vous apprendrez à configurer un projet, définir un schéma, écrire des résolveurs et tester l'API via GraphiQL. Prêt ? C'est parti !
1. Configuration du projet
1.1. Création d'une application Spring Boot
Tout d'abord, créons un nouveau projet sur Spring Initializr. Sélectionnez :
- Projet : Gradle (Kotlin)
- Langage : Kotlin
- Spring Boot : 3.2+
- Dépendances : Spring Web, Spring Boot DevTools
Après le téléchargement, ajoutez la dépendance GraphQL au fichier build.gradle.kts :
dependencies { implementation("com.expediagroup:graphql-kotlin-spring-server:7.0.0") implementation("org.springframework.boot:spring-boot-starter-web") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") testImplementation("org.springframework.boot:spring-boot-starter-test")}1.2. Configuration de l'application
Créez un fichier application.yml dans src/main/resources :
server: port: 8080
graphql: packages: - "com.example.graphql.demo"Cela demandera à Spring Boot de scanner le package com.example.graphql.demo pour les résolveurs et les types.
2. Définition du schéma GraphQL
2.1. Création du modèle de données
Créons un modèle simple pour un livre et un auteur. En Kotlin, nous utilisons des classes de données :
// src/main/kotlin/com/example/graphql/demo/model/Book.ktpackage com.example.graphql.demo.model
data class Book( val id: String, val title: String, val author: Author, val year: Int)
data class Author( val id: String, val name: String, val books: List<Book> = emptyList())2.2. Définition du schéma via le code (SDL)
Au lieu d'écrire un fichier schema.graphqls, nous utiliserons les annotations @GraphQLDescription et @GraphQLIgnore. La bibliothèque graphql-kotlin génère automatiquement le schéma à partir des classes. Cependant, pour plus de clarté, créons un fichier schema.graphqls dans src/main/resources :
type Query { books: [Book!]! book(id: String!): Book authors: [Author!]!}
type Mutation { addBook(title: String!, authorId: String!, year: Int!): Book!}
type Book { id: String! title: String! author: Author! year: Int!}
type Author { id: String! name: String! books: [Book!]!}3. Implémentation des résolveurs
3.1. Service de stockage des données
Pour simplifier, nous utiliserons un stockage en mémoire :
// src/main/kotlin/com/example/graphql/demo/service/LibraryService.ktpackage com.example.graphql.demo.service
import com.example.graphql.demo.model.Authorimport com.example.graphql.demo.model.Bookimport org.springframework.stereotype.Serviceimport java.util.UUID
@Serviceclass LibraryService { private val authors = mutableListOf( Author(id = "1", name = "George Orwell"), Author(id = "2", name = "Ray Bradbury") )
private val books = mutableListOf( Book(id = "1", title = "1984", author = authors[0], year = 1949), Book(id = "2", title = "Fahrenheit 451", author = authors[1], year = 1953) )
fun getBooks(): List<Book> = books fun getBook(id: String): Book? = books.find { it.id == id } fun getAuthors(): List<Author> = authors fun getAuthor(id: String): Author? = authors.find { it.id == id }
fun addBook(title: String, authorId: String, year: Int): Book { val author = authors.find { it.id == authorId } ?: throw IllegalArgumentException("Author not found") val book = Book(id = UUID.randomUUID().toString(), title = title, author = author, year = year) books.add(book) return book }}3.2. Résolveur de requêtes
Créez un résolveur pour les requêtes :
// src/main/kotlin/com/example/graphql/demo/resolver/QueryResolver.ktpackage com.example.graphql.demo.resolver
import com.example.graphql.demo.model.Authorimport com.example.graphql.demo.model.Bookimport com.example.graphql.demo.service.LibraryServiceimport org.springframework.stereotype.Component
@Componentclass QueryResolver(private val libraryService: LibraryService) {
fun books(): List<Book> = libraryService.getBooks()
fun book(id: String): Book? = libraryService.getBook(id)
fun authors(): List<Author> = libraryService.getAuthors()}3.3. Résolveur de mutations
Créez un résolveur pour les mutations :
// src/main/kotlin/com/example/graphql/demo/resolver/MutationResolver.ktpackage com.example.graphql.demo.resolver
import com.example.graphql.demo.model.Bookimport com.example.graphql.demo.service.LibraryServiceimport org.springframework.stereotype.Component
@Componentclass MutationResolver(private val libraryService: LibraryService) {
fun addBook(title: String, authorId: String, year: Int): Book { return libraryService.addBook(title, authorId, year) }}4. Test de l'API
4.1. Lancement de l'application
Exécutez l'application via la classe principale ou en utilisant la commande :
./gradlew bootRunAprès le démarrage, le point de terminaison GraphQL sera disponible à l'adresse http://localhost:8080/graphql, et l'interface GraphiQL à l'adresse http://localhost:8080/graphiql.
4.2. Exemples de requêtes
Ouvrez GraphiQL et exécutez les requêtes suivantes :
Récupérer tous les livres :
query { books { id title author { name } year }}Récupérer un livre par son ID :
query { book(id: "1") { title author { name } }}Ajouter un nouveau livre :
mutation { addBook(title: "Brave New World", authorId: "1", year: 1932) { id title author { name } }}Conclusion
Nous avons créé une API GraphQL entièrement fonctionnelle en utilisant Kotlin et Spring Boot. Dans ce tutoriel, nous avons couvert les étapes de base : configuration du projet, définition du schéma, implémentation des résolveurs et test. GraphQL offre des capacités puissantes pour une récupération flexible des données, et Kotlin rend le code concis et sûr.
Pour approfondir, nous vous recommandons d'explorer les abonnements, la gestion des erreurs et l'intégration avec les bases de données. Bonne continuation dans votre développement !