Skip to content

IMPORTANT

GraQL is prerelease, experimental, and a demonstration piece. Use at your own risk.

Quickstart

This page is designed to help you quickly make the leap from micronaut®'s basic GraphQL integration to a low-configuration, team-friendly, sensible-default workflow for publishing GraphQL APIs.

The Problem: GraphQLFactory

Leaping straight from micronaut®'s GraphQL dependency to writing code leaves your team maintaining a GraphQL "factory" bean.

All contributors must register every query, mutation, and fetch with a growing pile of boilerplate code:

kotlin
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
    .type("Query", typeWiring -> typeWiring  
            .dataFetcher("books", bookDataFetcher))

    .type("Mutation", typeWiring -> typeWiring 
            .dataFetcher("createBook", createBookDataFetcher)
            .dataFetcher("readBook", readBookDoDataFetcher))

    .type("Book", typeWiring -> typeWiring 
            .dataFetcher("author", authorDataFetcher))
    .type("Magazine", typeWiring -> typeWiring 
            .dataFetcher("author", authorDataFetcher))

    .build();

GraQL's Solution

GraQL's solution isn't groundbreaking: annotate your existing code, similar to Netflix DGS and Spring GraphQL.

With good naming practices and single-argument methods, there's barely anything to do:

kotlin

/*
Annotate any existing controller or create a GraphQL-specific component with 
@GraQLComponent to mark it singleton providing GraphQL data fetchers.  
*/
@GraQLComponent
class BookController(
    private val bookService: BookService,
    private val authorService: BookService,
) {

    /*
    Register a Query with @GraQL, defaulting to the method name as 
    the name of the GraphQL dataFetcher.
    */
    @GraQLQuery
    fun books(request: FindBooksRequest?): Collection<Book> {
        /* Any typical format-specific controller-tier stuff here! */
        /* ...stuff... */
        
        /* Ok, delegate to a service */
        return bookService.findBooks(request ?: FindToDosRequest())
    }
    
    /*
    Register a Mutation with @GraQL, defaulting to the method name as 
    the name of the GraphQL dataFetcher.
    */
    @GraQLMutation
    fun createBook(request: CreateBookRequest): CreateBookResponse {
        return bookService.createBook( request )
    }

    /*
    GraQL encourages *immediate addressing of the N+1 problem* by favoring
    batch fetches! When books are listed and the consumer requests their
    authors, GraQL will batch-fetch authors instead of seeking them for
    each Book in the result.
     */
    @GraQLBatchFetch
    fun author( books:Collection<Book> ): List<Book> {
        // Find all of our authors, at once, by ID
        return authorService.findAuthorsByIdIn( books.map{it.authorId} )
    }

}