Cloud-native application made ease: developing an application with Quarkus and Apache Ignite


In this very short tutorial, I am going to demonstrate how to develop a cloud-native application by using Quarkus and in-memory databases. The duration of this tutorial will not longer than 10 minutes. If you don't familiar with Quarkus and Apache Ignite, please take a few moments to read the previous tutorials.

Disclaimer, at these moments Apache Ignite under-the-hood uses Java reflection to complete database operation, so there are no straightforward ways to build a native executable through GraalVM.

So, we are going to do the following steps to complete the tutorial:

  1. Install and run an Apache Ignite in-memory database

  2. Run a few SQL scripts for initializing the dataset.

  3. Build a simple cloud-native application which will read data from the Apache Ignite database.

Before we start, a few considerations need to be taken into account to build and run the Quarkus application.

  1. JDK. Open JDK or Oracle JDK 11 or above

  2. Maven version 3.6.3 or above

  3. Any text editor

First of all, we are going to install an Apache Ignite in-memory database and populate the sample dataset.

The complete source code of the article is available in the GitHub repository.

Step 1. Installing and setting up Apache Ignite

Download the distribution archive from the Ignite website. Extract the distribution archive in any directory, for instance, /opt/apache-ignite. Use the following *nix command to extract the archive as shown below:

unzip apache-ignite-fabric-{VERSION}-bin.zip -d /opt/apache-ignite

Step 2. Configure the Apache Ignite

Set an environment variable IGNITE_HOME to the created directory apache-ignite and add the bin directory of the apache-ignite to the PATH environment variable:

export IGNITE_HOME=YOUR_IGNITE_HOME_PATH 
export PATH=$PATH:$JAVA_HOME/bin:$IGNITE_HOME/bin:$HOME/bin

Step 3. Populate the dataset

Run the following bash command to connect to the Ignite node through Ignite SQLLINE

sqlline.sh --verbose=true -u jdbc:ignite:thin://127.0.0.1/

Create two tables (Person and Tweets) with the following DDL SQL scripts.

CREATE TABLE Person (id LONG PRIMARY KEY, name VARCHAR, nick VARCHAR) WITH "template=replicated";

CREATE TABLE TWEETS (id LONG, tweet VARCHAR, person_id LONG, PRIMARY KEY (id, person_id)) WITH "backups=1, affinityKey=person_id";

Table Person will store all the user's profiles such as Surname and Nickname. On the other hand, table Tweets will keep all the tweets that a user has done. Note that, Tweets entity related with the Person entity through an affinity key: person_id


Step 4. Creating the Quarkus application structure Open a terminal and run the following Maven command to create a Quarkus project.

mvn io.quarkus:quarkus-maven-plugin:1.5.2.Final:create \
    -DprojectGroupId=com.blu.std \
    -DprojectArtifactId=quarkus-ignite \
    -DclassName="com.blu.std.quarkus.Tweets" \
    -Dpath="/tweet" 

The above command will create a complete maven project with a Java class named "Tweets" exposed an endpoint on /tweet. Also, an application configuration file and examples of Docker files also created in /src/main/docker directory. Take a few moments and check the project structure.

Now, add an Ignite maven dependency as shown below:

<dependency>
    <groupId>org.apache.ignite</groupId>
    <artifactId>ignite-core</artifactId>
    <version>2.8.0</version>
</dependency>

Step 5. Add Java class which will return a pre-configured Ignite thin client connection

Create a new Java class name IgniteConfiguration into the com.blu.std.quarkus package. Add the following pseudo-code:

@ApplicationScoped
public class IgniteConfiguration {

    private static final Logger LOGGER = LoggerFactory.getLogger(IgniteConfiguration.class);

    @ConfigProperty(name = "host")
    String HOST;
    @ConfigProperty(name = "port")
    String PORT ;

    @Produces
    public Optional<IgniteClient> getIgniteClient(){

        ClientConfiguration cfg = new ClientConfiguration().setAddresses(getHOST()+":"+getPORT());

        LOGGER.info("Ignite client configured to host:" + getHOST() + " at port:" + getPORT());

        Optional<IgniteClient> igniteClient = Optional.empty();

        try{
            igniteClient = Optional.ofNullable(Ignition.startClient(cfg));

        } catch(ClientException e) {
            e.printStackTrace();
        }

        return igniteClient;
    }

Please, check the Github repository for the entire code. The above code snippet is very straightforward, we use @ConfigProperty annotation to inject the HOST and PORT configuration parameter form the application.properties file. Next, we initialized an Ignite thin client connection which returns an IgniteClient instance. Moreover, we use an Optional class as a container object which will help us to get rid of the null pointer exception.


Step 6. Add a new REST endpoint

Modify the "Tweets" Java class and add the following code snippet:

@Inject
IgniteConfiguration ignite;

@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/byprofile/{nick}")
public String getTweetByProfile(@PathParam("nick") String nickname) {
    logger.info("/byprofile/{nick} API invoked, method arg:" + nickname);

    if(ignite.getIgniteClient().isPresent()){

        ClientCache<Long, String> clientCache = ignite.getIgniteClient().get().cache(CACHE_NAME);

        String qry = "SELECT p.name, t.tweet\n" +
                "FROM Person p, Tweets t\n" +
                "WHERE t.person_id = p.id " +
                "and p.nick = ?";
        List<List<?>> rows = clientCache.query(new SqlFieldsQuery(qry).setArgs(nickname)).getAll();

        return rows.get(0).get(1).toString();

    } else {
        return "Exception occurs!!";
    }
} 

We just added a vanilla Java method named "getTweetByProfile" exposed on "/byprofile/{nick}" endpoint, which will return a 'Tweet' by a user nickname. The method uses Ignite SqlFieldsQuery to execute an SQL query to query the user tweet's by user nickname.


That's it, you now have a working example of a cloud-native application that works with an in-memory database like Apache Ignite. The project will have built an Application jar file for the sample application. Run it to check that everything works correctly.


Step 7. Compile, build, and run the Application.

To build the project, run the following command from the project home directory.

mvn clean install

At this point, the project is ready to run. Execute the following command from the project home directory.

java -jar ./target/quarkus-ignite-1.0-SNAPSHOT-runner.jar

You should see output similar to the following:

Use curl in another terminal and put the service through its paces:

srb-wsn-0000336:~ shamim$ curl -w "\n" http://localhost:8080/tweet/byprofile/RealDonaldTrump
MAKE AMERICA GREAT AGAIN!

Summary

In this blog post, we learned how to build a basic Quarkus web application that can store and read data from an in-memory database.


Homework.

None ;-)

Please Note

email us at:

  • Twitter
  • LinkedIn
Join our mailing list

© 2020 Shamim bhuiyan