Microservices with Quarkus – GraphQL API+ Reactive MySQL

Quarkus(https://quarkus.io) is a Subatonic Java framework. Its specially designed for micro-services and similar to Micronaut.Usually SpringBoot comes with lot of features inbuilt and bit heavy solution if we are focusing more on micro-service patterns such as Reactive Streams, Messaging, Low latency API calls etc .Quarkus has a quick boot time compared to Spring Boot and designed as “Container First” strategy.

In this article I am going to illustrate how we combine super cool features such as GraphQL, Reactive SQL together and build high performing micro-service component.

Please use this Git Repo as a reference :

https://github.com/dumindarw/graphql-quarkus

Step 1: Creating Quarkus Project

Quarkus echo-system contains lot of cool and great extension list, in this project I am going to use below extensions.

quarkus-vertx-graphql – Eclipse VertX GraphQL plugin integration with Quarkus
graphql-java-extended-scalars – Support for scalar types such as Date, Time etc.
quarkus-resteasy – REST library comes with Quarkus
quarkus-reactive-mysql-client – MySQL reactive support library
quarkus-config-yaml – Enable YAML extension instead of legacy property files

mvn io.quarkus:quarkus-maven-plugin:1.2.1.Final:create \
    -DprojectGroupId=com.duminda \
    -DprojectArtifactId=quarkus-graphql-project \
    -Dextensions="reactive-mysql-client,config-yaml,vertx-graphql,resteasy"

After creating the project go to “quarkus-graphql-project” add below dependency manually.

<dependency>
  <groupId>com.graphql-java</groupId>
  <artifactId>graphql-java-extended-scalars</artifactId>
  <version>1.0</version>
</dependency>

Rename application.properties to application.yml

Step 2: Create GraphQL types and scalars

Create group.graphqls file inside your resources folder and add Types, Functions etc.

scalar Date

type Group {
  id: String
  name: String
  createdBy: String
  createdDate: Date
  blacklisted: Boolean
}

type Query {
  allGroups(isBlackListed: Boolean = false): [Group]
}

type Mutation {
  addGroup( name: String, createdBy: String): Boolean
}

Here I have a one model called Group , one Query function, and one Mutation function

Create same model as a POJO class (Group.java)

Step 3: Service layer implementation

MySQL table model (tbl_mygroups)

In group.graphqls file I have two functions called allGroups and addGroup. We have to create those two methods inside our service layer.

public CompletionStage<List<Group>> allAvailableGroups(DataFetchingEnvironment env) {
	boolean isBlackListed = env.getArgument("isBlackListed");

	return client.query("SELECT id, name, createdBy, createdDate, blacklisted FROM tbl_mygroups")
			.thenApply(rowSet -> {
				List<Group> list = new ArrayList<>(rowSet.size());
				for (Row row : rowSet)
					if (!isBlackListed)
						list.add(from(row));

				return list;
			});
}

In above method inside our service class returns asynchronous computation.
Since our mysql query function returns reactive stream we have to pass the returning data to our API layer which is GraphQL Observable Router.

public void init(@Observes Router router) {

	GraphQL graphQL = setupGraphQL();
	GraphQLHandler graphQLHandler = GraphQLHandler.create(graphQL);

	router.route("/graphql").handler(graphQLHandler);
}

Another important part is RuntimeWiring

RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
			.type("Query", builder-> builder.dataFetcher("allGroups", taskRepo::allAvailableGroups))
			.type("Mutation",builder -> builder.dataFetcher("addGroup", taskRepo::addGroup))
			.scalar(ExtendedScalars.Date)
			.build();

We have to call our Repo functions(allAvailableGroups, addGroup) during runtime and add to our GraphQL APIs(allGroups, addGroup).

Step 4: Database configurations (application.yml)

quarkus:
  http:
    port: 8088
  datasource:
    url: vertx-reactive:mysql://x.x.x.x:3306/test_db
    username: user
    password: pass

Step 5: Run project in development mode

./mvnw compile quarkus:dev

Step 6: Access GraphQL browser and call APIs

http://localhost:8088/graphql-ui/

#Query API to get all groups

query {
  allGroups {
    id,
    name
  }
}

#Mutation to add new group

mutation{
  addGroup(name:"TestGroup",createdBy:"Rajitha")
}

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