In this article, we will implement a Micronaut application written in Java that uses GraphQL to expose the data. Let’s have a quick overview of the GraphQL and Micronaut frameworks before we move on to the implementation.
GraphQL
“GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.“
This technology was developed by Facebook for querying the existing data in a declarative way. The client can specify the precise data it requires, traverse child resources with a single request, and execute multiple queries with only a single request.
Micronaut
“A modern, JVM-based, full-stack framework for building modular, easily testable microservice and serverless applications.”
Micronaut offers several capabilities comparable to already-existing frameworks like Spring, but it also has some unique characteristics that make it stand out. It also provides a number of options to develop applications with support for Java, Groovy, and Kotlin.
Now, that we have some idea about the two frameworks let’s stitch them together in the implementation.
Implementing GraphQL with Micronaut
Generate Micronaut application
We have the option of generating the Micronaut application using the Micronaut Command Line Interface or with the Micronaut Launch. Here, we are using the launch option to generate the application by choosing the below options
- Application Type as Micronaut Application
- Java version 11
- Name of the application: “micronaut-with-graphql”
- Base package name: “com.knoldus.micronaut”
- Click on the Features button and choose graphQL dependency
- Click on Generate Project

Describe the schema
By default GraphQL endpoint /graphql
is enabled so you don’t need to add any extra configuration. Create the file schema.graphqls
in resources directory:
src/main/resources
type Query {
employeeById(id: ID): Employee
}
type Employee {
id: ID
name: String
empId: Int
address: Address
}
type Address {
id: ID
addressLine1: String
addressLine2: String
}
Implement Model classes
Create Employee
and Address
classes that will mimic the data we want to expose:
src/main/com/knoldus/micronaut/dto/Employee.java
package com.knoldus.micronaut.dto; import io.micronaut.core.annotation.Introspected; @Introspected public class Employee { private final String id; private final String name; private final int empId; private final Address address; public Employee(String id, String name, int empId, Address address) { this.id = id; this.name = name; this.empId = empId; this.address = address; } public String getId() { return id; } public String getName() { return name; } public int getEmpId() { return empId; } public Address getAddress() { return address; } }
src/main/com/knoldus/micronaut/dto/Address.java
package com.knoldus.micronaut.dto;
import io.micronaut.core.annotation.Introspected;
@Introspected
public class Address {
private final String id;
private final String addressLine1;
private final String addressLine2;
public Address(String id, String addressLine1, String addressLine2) {
this.id = id;
this.addressLine1 = addressLine1;
this.addressLine2 = addressLine2;
}
public String getId() {
return id;
}
public String getAddressLine1() {
return addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
}
Data Repository
Create a database repository that will pull the data from the database and make it available for the client. To keep this example simple, instead of retrieving the information from a database we will keep it in memory and just return it from there.
src/main/com/knoldus/micronaut/repository/DbRepository.java
package com.knoldus.micronaut.repository; import com.knoldus.micronaut.dto.Address; import com.knoldus.micronaut.dto.Employee; import jakarta.inject.Singleton; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Singleton public class DbRepository { private static final List<Employee> EMPLOYEES = Arrays.asList( new Employee("employee-1", "John Doe", 223, new Address("addr-1", "SmallVille", "DC")), new Employee("employee-2", "Moby Simons", 635, new Address("addr-2", "Gotham", "DC")), new Employee("employee-3", "Jennifer Stone", 371, new Address("addr-3", "Khandaq", "DC")) ); public List<Employee> findAllBooks() { return EMPLOYEES; } public List<Address> findAllAuthors() { return EMPLOYEES.stream() .map(Employee::getAuthor) .collect(Collectors.toList()); } }
Data Fetchers
With a Data Fetcher, we bind the GraphQL schema, and our domain model and execute the appropriate queries in our datastore to retrieve the requested data.
src/main/com/knoldus/micronaut/config/GraphQLDataFetchers.java
package com.knoldus.micronaut.config; import com.knoldus.micronaut.dto.Address; import com.knoldus.micronaut.dto.Employee; import com.knoldus.micronaut.repository.DbRepository; import graphql.schema.DataFetcher; import jakarta.inject.Singleton; @Singleton public class GraphQLDataFetchers { private final DbRepository dbRepository; public GraphQLDataFetchers(DbRepository dbRepository) { this.dbRepository = dbRepository; } public DataFetcher<Employee> getEmployeeByIdDataFetcher() { return dataFetchingEnvironment -> { String employeeId = dataFetchingEnvironment.getArgument("id"); return dbRepository.findAllBooks() .stream() .filter(employee -> employee.getId().equals(employeeId)) .findFirst() .orElse(null); }; } public DataFetcher<Address> getAdressDataFetcher() { return dataFetchingEnvironment -> { Employee employee = dataFetchingEnvironment.getSource(); Address addressBook = employee.getAuthor(); return dbRepository.findAllAuthors() .stream() .filter(address -> address.getId().equals(addressBook.getId())) .findFirst() .orElse(null); }; } }
- Constructor injection for the DbRepository bean
- Return a GraphQL dataFetchingEnvironment with the information about the query
- Get the id parameter from the query
- Access the repository to find the book. Remember that this should be backed by a real datastore
- Get the Employee related to a specific address
- Get the Address
- Access the repository to find the Address.
Factory
Create the following factory that will bind the GraphQL schema to the code and types.
src/main/com/knoldus/micronaut/config/GraphQLFactory.java
package com.knoldus.micronaut.config; import graphql.GraphQL; import graphql.schema.GraphQLSchema; import graphql.schema.idl.RuntimeWiring; import graphql.schema.idl.SchemaGenerator; import graphql.schema.idl.SchemaParser; import graphql.schema.idl.TypeDefinitionRegistry; import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.Factory; import io.micronaut.core.io.ResourceResolver; import jakarta.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Optional; import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring; @Factory public class GraphQLFactory { private static final Logger LOG = LoggerFactory.getLogger(GraphQLFactory.class); @Bean @Singleton public GraphQL graphQL(ResourceResolver resourceResolver, GraphQLDataFetchers graphQLDataFetchers) { SchemaParser schemaParser = new SchemaParser(); TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry(); Optional<InputStream> graphqlSchema = resourceResolver.getResourceAsStream("classpath:schema.graphqls"); if (graphqlSchema.isPresent()) { typeRegistry.merge(schemaParser.parse(new BufferedReader(new InputStreamReader(graphqlSchema.get())))); RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring() .type(newTypeWiring("Query") .dataFetcher("employeeById", graphQLDataFetchers.getEmployeeByIdDataFetcher())) .type(newTypeWiring("Employee") .dataFetcher("address", graphQLDataFetchers.getAdressDataFetcher())) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring); return GraphQL.newGraphQL(graphQLSchema).build(); } else { LOG.debug("No GraphQL services found, returning empty schema"); return new GraphQL.Builder(GraphQLSchema.newSchema().build()).build(); } } }
- Annotate the class with @Factory so the Micronaut framework knows that this class will create beans
- Create a new SchemaParser
- Get the previously created schema.graphqls file from the classpath
- Parse the schema
- Create the runtime wiring
- Bind a data fetcher for the employeeById query
- Bind a data fetcher to retrieve the author related to a book
- Create the executable schema
- Return the GraphQL bean
Run the application
To run the application, use the ./mvnw mn:run
command, which starts the application on port 8080.
Run the following curl command
curl -X POST 'http://localhost:8080/graphql' -H 'content-type: application/json' --data-binary '{"query":"{ employeeById(id:\"employee-1\") { name, empId, address { addressLine1, addressLine2} } }"}'
You will get the below result

Conclusion
This is how we can implement GraphQL in a micronaut application. As we can see it is pretty simple to fetch data in a single query call and this can be utilized in the event-based CQRS architecture to have a simple and clean query service.
Reference
https://guides.micronaut.io/latest/micronaut-graphql-gradle-java.html