I first heard of KumuluzEE in 2015 when it won Java Duke’s Choice Award. I must admit that I didn’t pay much attention to it so far. Maybe because KumuluzEE people do not make much noise.
KumuluzEE at a glance
According to its own definition, KumuluzEE is “a lightweight open-source microservice framework”.
It is published under the MIT license, free of charge for unlimited usage and GitHub issues support. Commercial support is available for 24/7 operations.
More precisely, it enables to develop microservices with Java EE/Jakarta EE technologies and extend them with Node.js, Go and other languages. It is compliant with Eclipse MicroProfile 1.x and 2.x.
It also provides support for other cloud-native functionalities:
- Service discovery with support for etcd and Consul,
- REST extensions for simple paging, querying and filtering,
- Logging framework for centralized log management,
- Event Streaming extensions for Apache Kafka,
- Reactive extensions for Vert.x,
- gRPC support,
- Ethereum support,
- Last be not least, GraphQL support which is the main reason for this blog.
It terms of scope and approach, it looks more like an integration framework than a strict implementations of the specifications.
My first impression has been rather positive, the documentation seems good and there are plenty of exemples.
KumuluzEE follows a “best of breed” approach by picking up various frameworks and libraries from the Java ecosystem: Jetty (Servlet, WebSocket), Jersey (JAX-RS), Weld (CDI), Hibernate Validator (Bean validation), Yasson (JSON-B), EclipseLink and Hibernate (JPA), Narayana (JTA), HikariCP (database connection pool), …
When building an application, an executable UBAR JAR embedding all classes (application + runtime) is created thanks to a specific Maven plugin.
Focus on KumuluzEE GraphQL
GraphQL is a KumuluzEE extension based on a GraphQLExtension class defined as a Java Service Provider. This class registers GraphQLServlet with the configured path (by default /graphql).
GraphQLServlet works as follow:
- Initializes the GraphQL schema and engine, both CDI and non-CDI contexts are supported,
- Process each HTTP request (POST/GET): prepares the GraphQL query, executes it against the engine, formats and returns a response,
- Optionally the engine can be rebuilt upon each query (makes sense when using DataLoader).
Basically, KumuluZEE GraphQL enables and facilitates the use of spqr annotations by applications: @GraphQLQuery, @GraphQLMutation, @GraphQLArgument, @GraphQLContext …
It provides 2 additional specific annotations:
- @GraphQLClass: to identify classes to be added to the schema (those using spqr annotations),
- @GraphQLApplicationClass: enables application classes to be scanned for adding custom graphql-java configuration.
AnnotationProcesor is another important part of the puzzle:
- It detects @GraphQLClass annotated classes for later use by GraphQLServlet file,
- It detects @GraphQLApplicationClass annotated classes and declare them as Java Service Provider,
- AnnotationProcessor is itself a Java Service Provider.
There are 2 levels of configuration:
- The first one is a generic KumuluzEE config.yaml file,
- The second one is based on GraphQLApplication classes enabling custom graphql-java configuration:
- Custom contexts,
- Custom instrumentations,
- Custom execution strategies for query, mutation and subscription,
- Custom request caching with preparsed document provider,
- Custom execution id provider,
- Change endpoint to create GraphQL object per request (if you are using DataLoaders).
A default GraphQLApplication class is provided with no option. Custom configuration is obtained by extending this class and annotating the new class class with @GraphQLApplicationClass.
A glimpse at the examples
Two samples are provided:
- graphql-jpa-sample: demonstrates how to expose a single JPA entity (Customer) through a GraphQL API,
- graphql-advanced: a more complex example based on 3 JPA entities (Assistant, Lecturer, Student) using pagination, filtering, ordering on queries and optimizing JPA queries.
Migrating spqrdemo to KumuluzEE
To give KumuluzEE GraphQL a try, I’ve decided to migrate my spqrdemo project to KumuluzEE “as is”. As a reminder, spqrdemo is a simple example showing how to use spqr in a CDI context. JNoSQL is used to access a MongoDB database.
I’ve started by initializing a project using the KumuluzEE project generator with the following option:
- KumuluzEE version: 3.2.0-SNAPSHOT,
- Features: generates UBER JAR (this adds the repackage goal to the Maven plugin),
- Components: Servlet 3.1, JAX-RS 2.1, CDI 2.0,
- Projects: KumuluzEE GraphQL.
A simple and clean pom.xml has been generated. Good starting point …
I’ve created a standard Maven project in my favorite IDE, copy the generated pom.xml and manually added JNoSQL, lombok and slf4j-jdk14 dependencies.
I also had to manually add kumuluzee-graphql-ui dependency to enable graphql-ui extension. It seems that this option is not proposed by the generator for the moment.
The refactoring couldn’t have been easier:
- I’ve copied all classes from spqrdemo except the cdi subpackage. The purpose of this subpackage was to automatically generate the schema and KumuluzEE has its own mechanism for that,
- I’ve replaced my @GraphQLComponent annotation by @GraphQLClass which is (more or less) the equivalent,
- I’ve configured KumuluzEE to activate graphiql,
- an UBER JAR of about 20 MB has been created in the target directory,
- I’ve run it with: java -jar.
And guess what? It just worked … I’ve run it with both Java 8 and 11 and it was OK!
This first try with KumuluzEE has been successful:
- I’ve discovered another Java/Jakarta EE and MicroProfile platform,
- It is well documented with plenty of examples,
- Beyond GraphQL, there are many features I would like to investigate.
In particular, KumuluzEE GraphQL has been easy-to-use and is a good source of inspiration for the MicroProfile GraphQL specification and its future implementations. For instance:
- enabling custom graphql-java configuration: the use of graphql-java is hidden and thanks to this mechanism, it is nevertheless possible to configure it in a specific way,
- utilities for pagination, ordering, filtering and optimized JPA queries. It makes sense to ensure efficient end-to-end processing of queries which is a challenge with GraphQL.
From now on, I will follow KumuluzEE …