Pages

Wednesday, February 13, 2019

Quick Microservice With Gradle Spring Boot Docker

A few years ago if you would have asked me to create a quick POC backend service with some rest APIs I would have just picked up NetBeans and created the REST APIs using jersey/glassfish (reference implementation of JSR 311 RESTful Web Services) from the UI itself.   While the above is an example of creating REST APIs bottom-up from the Database layer, once can plug business logic by adding few more java classes or a service layer. Lately, I have been using Spring Boot a lot in production and it really makes the developer's life easy by not having to write a lot of boilerplate code. Annotations take care of Dependency injection, singleton, REST API mappings etc. It even has the embedded Jetty web server to run the service locally without really having to install a bulk of binary like Glassfish/Tomcat server and deploy them (comes integrated with Netbeans tough - one could right click and run the service). However, Spring Boot + Gradle makes the code ultraportable. All you need to do is check-out from the code repo and run Gradle/Spring Boot command to build or run. Even the testing tools can be easily added to gradle and both Unit and Integration test can be written. There are so may example of hello world with Spring Boot and Gradle on the internet, but I thought of keeping a copy of simple skeleton of service which I can use to bootstrap any app in future. Even better - dockerize the app and create an image out of it which can run anywhere irrespective of the host machine and its setup. Later we can also push it to a public container registry and use it in Minikube or Kubernetes in the cloud (probably in a separate post).

I assume one has installed Java and gradle (only needed for creating the project but the subsequent setup will be taken care by gradlew, the wrapper which can download gradle itself)

Code

To create a skeleton
gradle init  --type java-application
Now add the spring boot dependencies in build.gragle. 

plugins {
...
id 'com.gradle.build-scan' version '1.16'
id 'org.springframework.boot' version '2.0.5.RELEASE'
}


dependencies {
// This dependency is found on compile classpath of this component and consumers.
implementation 'org.springframework.boot:spring-boot-dependencies:2.0.5.RELEASE'
implementation 'org.springframework.boot:spring-boot-starter-web:2.0.5.RELEASE'
}

Create the launcher application which can start the server.


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}

Now tell gradle (in build.gradle)which one is the main class

bootJar {
mainClassName = 'hello.App'
}

The whole code can be checked out from
git clone https://github.com/neilghosh/simple-gradle-springboot-service

Build 

Now one can build the jar with all the dependencies
./gradlew bootJar
the jar will be created in the ./build directory.

Run


Now we can run the app by either
./gradlew bootRun
or run the jar itself
java -jar build/libs/simple-gradle-springboot-service .jar

Dockerize 

We can create the following simple Dockerfile to import the OpenJDK base image and copy the jar to an appropriiate directory and run command.

FROM openjdk:8-jdk-alpine
RUN mkdir -p /app/
ADD build/libs/simple-gradle-springboot-service.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Build the docker image
docker build . -t gradle-spring-boot-app
 Check the local image created
docker images
REPOSITORY                            TAG                 IMAGE ID              CREATED               SIZE
gradle-spring-boot-app                latest                21572d4766d3        About an hour ago   124MB

And run the docker image exposing the port to host
docker run -p 8080:8080 gradle-spring-boot-app:latest
Profit
$ curl http://localhost:8080/
Hello Gradle!
 Next, we will see how to push the local cached imaged to a docker registry and run in cloud or Minikube

No comments:

Post a Comment