Building a Simple Java Microservice Using Helidon MicroProfile APIs and JPA

This post talks about building a simple data bound microservice using Helidon framework. If you are new to Helidon, please take a step back and read the details in the official site : https://helidon.io

Let us get our hands dirty to get a feel of the offerings in Helidon framework.

Setting up the Environment

First step is to ensure you have installed all necessary tools required for building and running this example.

The above two are enough to build and run the service discussed in this post locally. However if you want to make your service cloud ready, please install r Docker, Kubectl and optionally Minikube as discussed in the following link: https://helidon.io/docs/latest/#/getting-started/01_prerequisites

Building a Simple Microservice with Helidon MicroProfile

Helidon lets you to build microservices in two flavors( programming model ):

  1. Helidon SE : With this approach, you will use vanilla Helidon WebServer, Config and Security APIs directly for building the desired services. These APIs follow functional programming style. This gives you more control on the execution of you code. However, this approach locks down the service implementation to Helidon and in future it will be very hard to port the implementation to different microservice platform such as Payara Micro.
  2. Helidon MP : With this approach, you will use Helidon MicroProfile(MP) APIs for building the services. MicroProfile specifies a collection of Java EE APIs such as CDI, JAX-RS for building portable Java microservices across various ‘microprofile’ (https://microprofile.io/) complaint platforms.

In this post we will use Helidon MP programming model for building the microservice. Let us get the ball moving.

  1. Generate the project with maven archetype
mvn archetype:generate -DinteractiveMode=false \
-DarchetypeGroupId=io.helidon.archetypes \
-DarchetypeArtifactId=helidon-quickstart-mp \
-DarchetypeVersion=0.10.5 \
-DgroupId=com.jobinesh.helidon.examples \
-DartifactId=dept-service-mp \
-Dpackage=com.jobinesh.helidon.examples.mp

2. Next is to set up a database for use in our example. You are free to choose database of your choice. This example uses a a very lightweight and simple database — SQLite. To learn more about SQLite, visit the following link: https://www.sqlite.org/index.html. SQLite is included in macOS and Mac OS X by default.

3. Define a Departments table in SQLite database.

CREATE TABLE departments
( department_id NUMBER(4)
, department_name VARCHAR2(30)
CONSTRAINT dept_name_nn NOT NULL
, manager_id NUMBER(6)
, location_id NUMBER(4)
) ;
CREATE UNIQUE INDEX dept_id_pk
ON departments (department_id) ;

4. As next step, we need to add necessary Java code in our example in order to read from/write to Department table. We will use Java Persistence API (JPA) for reading and writing data between Java objects and SQLite. As the source that we generated in Step 1 is not configured to use JPA, let us add that support.

5. Go to the generated project source and all required dependencies in the pom.xml. Here is the list of dependencies added for this example:

 <dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa.modelgen.processor
</artifactId>
<version>2.7.3</version>
</dependency>
<!-- SQLite driver --> 
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.25.2</version>
</dependency>

6. Add src/main/resources/META-INF/persistence.xml to the project. The persistence.xml file is a standard configuration file in JPA and it has to be included in the META-INF directory inside the JAR file that contains the entity beans. Here is the persistence.xml used for this example

<?xml version=”1.0" encoding=”UTF-8"?>
<persistence version=”2.1" xmlns=”http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=”http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name=”demo-pu” transaction-type=”RESOURCE_LOCAL”>
<class>com.jobinesh.helidon.examples.mp.model.Departments</class>
<properties>
<property name=”javax.persistence.jdbc.driver”
value=”org.sqlite.JDBC”/>
<property name=”javax.persistence.jdbc.url”
value=”jdbc:sqlite:/Users/jmpurush/mywork/sqlite/demo.db”/>
</properties>
</persistence-unit>
</persistence>

7. We are done with all basic configuration. Now you can add the JPA entities to the project source as appropriate. In this simple example we use only one entity, namely Departments. Here is the Departments JPA entity defined for Departments table: https://github.com/jobinesh/micro-java-samples/blob/master/helidon/dept-service-mp/src/main/java/com/jobinesh/helidon/examples/mp/model/Departments.java

8. Next steps is to build Restful resource class which will act as REST end points. We use JAX-RS APIs for building REST resource class. You can use JPA entities that you created in previous step in this class to read or write data from database while building REST APIs. The DepartmentResource class used in this example is available here: https://github.com/jobinesh/micro-java-samples/blob/master/helidon/dept-service-mp/src/main/java/com/jobinesh/helidon/examples/mp/DepartmentResource.java

9. Add the unit test cases as appropriate. Here is a basic example: https://github.com/jobinesh/micro-java-samples/blob/master/helidon/dept-service-mp/src/test/java/com/jobinesh/helidon/examples/mp/MainTest.java

10. To run this example, open terminal window, goto the root of the project and do the following :

mvn package
java -jar target/dept-service-mp.jar

11. To try out the REST APIs offered in this example, you and use curl utility and try the following:

1. Create a department 
curl -X POST -H "Content-Type: application/json" \
--data '{"departmentId":30,"departmentName":"Finance","locationId":1700,"managerId":200}' \
http://localhost:8080/departments
2. List all departments
curl -X GET http://localhost:8080/departments
3. Delete a department
curl -X "DELETE" http://localhost:8080/departments/30

The complete source code used for this example is available in the following git repository :

Congrats, we have finished building a simple microservice ! This is a simple example, primarily meant for illustrating the basics and usage pattern of data bound JAX-RS resource class when used along with Helidon.

What next ?

If you are keen on learning more on this topic, please check out this post: https://medium.com/@jobinesh/a-helidon-microprofile-sample-illustrating-all-commonly-used-jax-rs-apis-cf180e76b3cd

The views expressed on this post are my own and do not necessarily reflect the views of my employer.