GraphQL with KumuluzEE

In the context of my contribution to the recently started MicroProfile GraphQL initiative, I’ve decided to give KumuluzEE GraphQL a try in order to  get some interesting inputs.

KumuluzEE-GraphQL-Logo

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.

 

Technical overview

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.

In the following tests, I’ve used KumuluzEE GraphQL 1.0.0 which depends on graphl-java 9.2 and spqr 0.9.8. There is no dependency on graphql-java-servlet since it brings its own GraphQLServlet:

KumuluzEE-GraphQL-Arch

 

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.

 

Configuration

There are 2 levels of configuration:

  1. The first one is a generic KumuluzEE config.yaml file,
  2. 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:

  1. graphql-jpa-sample: demonstrates how to expose a single JPA entity (Customer) through a GraphQL API,
  2. 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.

graphql-ui is a companion extension that enables to run GraphIQL using http://localhost:8080/graphiql URL.

The refactoring couldn’t have been easier:

  1. 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,
  2. I’ve replaced my @GraphQLComponent annotation by @GraphQLClass which is (more or less) the equivalent,
  3. I’ve configured KumuluzEE to activate graphiql,
  4. an UBER JAR of about 20 MB has been created in the target directory,
  5. 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!

 

Conclusion

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 …

 

 

 

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s