Over the span of the past few months I’ve been learning about GraphQL and how to use it as an alternative to RESTful API development. The focus thus far had been around GraphQL and Golang as well as GraphQL and Node.js. I might have squeeze out all I can on those two development languages so I’ve decided to switch gears and press my luck with some Java.

In this tutorial, we’re going to see how to quickly get up and running with GraphQL using Java and the popular Spring Boot framework.

Before we get into things, I want to give credit where credit is deserved. Prithviraj Pawar wrote a great article titled, How to get Your GraphQL Java Server Up and Running in no Time, which gave me a lot of ideas even though there were things to be desired, such as a database instead of mock data. I encourage you to read his article after reading through mine.

The Requirements

There are a few prerequisites that must be met before we jump into the GraphQL and development side of things.

We’re going to assume that you already have Couchbase installed, configured, and running. Anything after Couchbase Server 5.0 will do because we’re only going to be using basic features.

We’re also going to assume that you’ve downloaded a Spring Boot base project. The Spring Boot website has a great generator that lets you define the dependencies. If you want to stay consistent to my guide, you’ll need to create a Gradle project rather than Maven.

Defining the Gradle Project Dependencies

When you have a Spring Boot template in hand, it will likely be very bare. We need to include the dependencies we plan to use in our Gradle configuration.

Open the project’s build.gradle file and include the following:

We’ll be using Spring Boot to serve our GraphQL endpoint, the Couchbase Java SDK for interactions with our database, and the GraphQL plugin for our query processing.

Bootstrapping the Java API with RESTful Endpoints

With the dependencies in place, we can start developing our API. Even though we’re using GraphQL as a replacement to all the common RESTful API stuff, it doesn’t mean that REST is completely out of the equation. We still need an endpoint to send our GraphQL queries to.

Depending on what you named your project, package, etc., open the file that contains your main function and include the following:

Remember, your package and class name may not match mine. Fill in the gaps where appropriate.

You’ll notice that we have two endpoints, where one is completely optional. I created the rootEndpoint as a way to test that my RESTful API was in fact working. The graphql endpoint is where we’re going to be spending our time. It expects a POST request as well as a request body. The request body will eventually be an actual GraphQL query, but for now we can leave it as is.

Designing a GraphQL Schema Document

Up until now we’ve only done some basic Spring Boot preparation work and nothing really related to GraphQL. For GraphQL to be possible, we need to know a defined schema that explains the queries that are available as well as the types of data that we are working with. There are numerous ways to do this, but we’re going to focus on a schema document.

Within the resources directory of your project, include a schema.graphql file that contains the following:

In case it isn’t obvious, we’re going to be working with Pokemon data. In the above file we’ve defined the queries that are available and the two data types that are available.

There are a variety of Pokemon games on the market and there are different Pokemon in each of the games, hence the relationship that we’ve defined. If you’re a true Pokemon fan you’ll know there is a little bit more to it than this, but for this example it is enough.

Developing the Fetching Logic for the Couchbase NoSQL Database

With the schema defined, we need to come up with database logic to be ran when a query is executed and that database logic must return results that match each of the two data types.

To make our lives a bit easier when it comes to project maintenance, we’re going to create a separate file for managing the database. Within your package, create a Database.java file that contains the following:

For the most part, the above set of functions should look familiar because we’ve defined them somewhat to match what we had in our GraphQL schema file.

A few things to note before we start filling each of the functions:

  1. The bucket will be defined in our main project file shortly after we define our logic.
  2. GraphQL expects a certain type of response, hence the extractResultOrThrow wrapper function that we’ve created.

With that noted, let’s start by creating the wrapper function. The extractResultOrThrow function will be used only on N1QL queries and it looks like the following:

Essentially we’re just looping through a N1QL result set and creating a List of Map from it.

Assuming that we have game data in our database, we can query for that data in the getGamesData function:

Using N1QL we can query for documents that match the type of game and process the results with our wrapper function. If you really wanted to be strict, instead of using a wildcard asterisk, you could define the properties that match your schema.

The next function, getPokemonData, will allow us to query for our Pokemon data in a similar fashion to how we did it with game data.

You’ll notice that we didn’t do anything new beyond change the type property. This is where things can get interesting. We have a data relationship for Pokemon in regards to game data. We could either fetch it in our current query or break it up to be more modular and potentially more light weight. We’re going to go with the modular and light weight option.

This brings us to our getGameData function:

There are two things happening in the above function, neither of which use N1QL.

In our schema we have defined an argument based query for game data as well as a data relationship in the Pokemon data. We’re going to accommodate both those scenarios in the same function.

Using the environment.getSource() function we can see if there is any parent data that goes with the request. An example of this parent data might be when we query for Pokemon data. The game field refers to the getGameData function while the other data such as the name, weight, or other, refers to the parent data. In the database, the game information is stored as an id so after we extract it from the parent data, we can do a lookup for game data.

The other scenario is if we pass an argument that represents a game id.

Both are valid and both do different things. In the end, we only want a single result rather than an array of results.

Wiring the Application Together for Successful GraphQL Processing

We are in the home stretch now. We’ve got our API and our database logic in place. The final step is to wire the GraphQL schema to the database logic and watch the results in all their glory.

Remember in the previous step I mentioned configuring our bucket information? Let’s take care of that first. Open the project’s application.properties file found in the resources directory. Include the following:

My database information is just an example. Make sure to replace it with the information that you’re using for your instance of Couchbase.

Back in your main project file, we can map the values and connect to our instance:

Notice that we’ve created two Bean and used the information from our properties file. Just like that we’re connected to Couchbase.

The next step is to initialize our GraphQL schema. There are numerous ways to do this, but I found it easier using the Spring Boot annotation for when the application starts:

The init function will be called when the application starts. It will load our schema file from the resources directory and define wiring. For example, we know that pokemons, games, and game(id: String) are all types of queries. Each get mapped to the appropriate database function and the open bucket is passed. Then we establish a mapping of game to the Pokemon type. We are more or less defining how fields and queries are tied to database interaction.

Once we build the schema we can tie it to our class variable. With the built schema, we can finalize our GraphQL RESTful endpoint:

In our endpoint we take the query string that was passed with the request and execute it with our built schema. The result will be whatever the client has asked for in the query.

So what does a query look like? Take the following for example:

The above query is probably not something anyone would ever need to run, but you could if you wanted to. In the above example we are querying for all Pokemon data and the game they are a part of. We are also querying for all games as well as a specific game. All three parts of the query are unrelated, but exist in the same query.

As a cool fun fact, in the pokemons query, if we choose not to query for game data, the database function is never called. GraphQL will only execute functions as they are needed.

Conclusion

You just saw how to build a GraphQL application using Spring Boot, Java, and Couchbase Server as the NoSQL database. As you saw in my sample query, we were able to query many different unrelated pieces of data in a single request, something that would have required several in a RESTful API.

For more information on using the Java SDK with Couchbase, check out the Couchbase Developer Portal.

Author

Posted by Madhuram Gupta

Leave a reply