Minborg

Minborg
Minborg
Showing posts with label Rest. Show all posts
Showing posts with label Rest. Show all posts

Friday, April 24, 2020

Java/Cloud: How to Quickly Create a Kubernetes-ready REST Microservice

Java/Cloud: How to Quickly Create a Kubernetes-ready REST Microservice 

It is safe to say that the Microservice + Cloud combination is all the rage these days. Microservices are being developed more than ever, in turn resulting in an increase in the number of application deployments. During the past decade, containerization and orchestration tools such as Docker and Kubernetes were developed, making the microservice pattern really easy to adopt.

This article will teach you how to generate a completely functional microservice with an exposed REST API capable of interacting with a MySQL database and deploy it to your local Kubernetes cluster. The learnings here can be applied to almost any database type like Oracle, SQL Server, DB2, and so on.

If you ever get stuck during the article, feel free to refer to the final version of the source code, which can be found in this GitHub repository.

Speed(ment) is Key 

As developers, one of the things we strive for in our everyday work is shorter development time.

At this point, we can already identify two aspects of our microservice that will make our development time longer than needed:

  1. We need to create a persistence layer 
  2. We need to expose a REST API


What if I were to tell you that a tool exists which can handle these things, without you having to write a single line of code?

Speedment is a Java ORM Toolkit and Runtime designed to allow developers to create super fast applications super fast. Speedment uses the native Java Streams API for database interaction, making it extremely easy to use for newcomers, seasoned veterans and anyone that falls in between. Speedment comes with a graphical tool, giving developers the ability to generate a Java representation of their database within seconds.

Furthermore, Speedment’s bundle system allows developers to easily expand the base functionality of the base Toolkit. One such enhancement is the Spring plugin which enables developers to generate a completely functional CRUD REST API in order to interact with their database.

In the remainder of the article, you will learn how to use the Speedment Tool to generate a working REST microservice and deploy it to a Kubernetes cluster. If you’re interested in Speedment as a whole, detailed documentation with examples can be found in the online manual.

Getting Started

Being distributed via Maven, Speedment is installation free but requires Java 8 or later. To get started, head over to the Speedment Initializer where you’ll be able to download a project template with all of the dependencies needed to create your microservice. These are the settings we will be using in the example:

If your setup is different, e.g. different database, make sure you apply the appropriate changes in the initializer.

Once you’re done configuring the project, click the Download button and unpack the downloaded zip-file. To launch the Speedment Tool, execute the following command from a terminal:

mvn speedment:tool


If this is your first time running the Speedment Tool, you’ll be asked to connect to your database. We’re running the vanilla MySQL Sakila sample database on our local machine, so the auth information would look like this:


Once you’ve filled in the required fields, click the Connect button. If the auth information you’ve provided was correct, you will be presented with the following screen:


Generating the Microservice

When you’ve connected to the database via the Speedment Tool, you can start configuring the various options that are available. There are a lot of options you can play around with, but for the purposes of this article, we will be focusing on the options that are needed to expose a REST API.

To enable REST API generation, click on the Project node in the tree view, and check the Enable REST option:



We’ve also enabled the Generate REST documentation option to automatically generate the OpenAPI documentation for our REST API. This option is not mandatory, but it will allow us to test our API more easily in the end.

The next step is optional, but it will make our REST routes a bit more aesthetically pleasing. Head over to the database schema node in the tree view and set the value of REST Endpoint to a front slash (/). By default, the schema name is included in the generated REST routes and this modification removes it.



Next, we’re going to enable the generation of REST controllers for the following tables:
  • Actor
  • Category
  • Customer
  • Film
  • Staff
  • Store

The steps to enable the controller generation are identical regardless of the table. For that reason we will only demonstrate them on the Actor table.

 Click the Actor table in the tree view and enable the Generate @RestController option. This, in turn, will enable several REST related options for that table. The options we are interested in, which you should enable, are:
  • REST Enable LIST
  • REST Enable GET
  • REST Enable CREATE
  • REST Enable UPDATE
  • REST Enable DELETE

We will also rename the REST Endpoint from /actor to /actors (again only for aesthetic purposes). By default, the REST Endpoint is named the same as the table it is associated with. In our case, the renaming makes sense, because when we visit the /actors endpoint, a list of actors will be retrieved, rather than a single actor.

Go ahead and repeat these steps for the other tables listed above. After you’re done, click the Generate button. This will generate a Java representation of your database along with the necessary REST configurations and controllers.

Running the Microservice


If we were to run our application right now as it is, it will most likely crash. This is because we haven’t specified the password our application should use to connect to the database.

When we generated our application, a bunch of Speedment-specific application properties were exposed. One such property is the spring.speedment.password property, which we can use to set the password Speedment will use to connect to our database.

There are a couple of ways to specify application properties. We’re going to be defining them in the application.properties file, which you should create in your application’s resources folder.

This is what our application.properties file looks like:

 # Application properties file - START
spring.application.name=speedment-spring-app

spring.speedment.password=sakila
# Application properties file - END

The default password for the Sakila database is sakila, but if your database has a different password, make sure those changes are reflected in the application.properties file.

Once we have everything configured, we can run our application. This is done by executing the following command from the project’s root folder:

mvn spring-boot:run


If you’ve enabled the Generate REST documentation option, you can visit http://localhost:8080/swagger-ui.html to access the REST API documentation:



You can execute your requests manually or directly from Swagger UI. If we were to visit http://localhost:8080/actors in our browser, we should get a JSON response with a list of actors stored in our database:
[
   {
      "actorId": 1,
      "firstName": "PENELOPE",
      "lastName": "GUINESS"
   },
   {
      "actorId": 2,
      "firstName": "NICK",
      "lastName": "WAHLBERG"
   },
   {
      "actorId": 3,
      "firstName": "ED",
      "lastName": "CHASE"
   },
... TRUNCATED ... 
]

Before Deployment

Before we start with the deployment process of our microservice, make sure you have the following dependencies installed on your local machine: Docker, kubectl, Minikube and Skaffold.

Dockerizing our Microservice

Before we can actually deploy our microservice to a Kubernetes cluster, we need to convert it into a format that Kubernetes can actually work with. Kubernetes is a container orchestration tool, so this is where Docker comes in to aid us with the container creation process.

In the root of your project, create a Dockerfile with the following contents:

FROM openjdk:11-slim-buster

EXPOSE 8080

ARG JAR_LOCATION=target
ARG JAR_NAME=speedment-spring-app
ARG JAR_VERSION=1.0.0

ADD ${JAR_LOCATION}/${JAR_NAME}-${JAR_VERSION}.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar", "--spring.speedment.host=sakila"]

The exported arguments (JAR_LOCATION, JAR_NAME, JAR_VERSION) may be different for your project, depending on the information you provided in the pom.xml file. From the root of your project, execute the following command:

mvn install


This will create a target folder with a JAR file containing your microservice. Make sure the name and the version of the file match with the information you put in the Dockerfile.

Creating the Deployment Configurations


We will be deploying two images to our Kubernetes cluster: the Sakila database and our microservice. The Sakila database already has a Docker image publicly available: restsql/mysql-sakila. However, we need to build an image for our microservice. This is where the Dockerfile we created earlier will come in handy. Later on, we will be using a tool called Skaffold to create an image for our microservice and use it in the deployment process.

Start by creating a folder called k8s in the root of your project. This is where you’ll store all of your Kubernetes Deployment and Service configurations. We will keep our microservice and database configurations separate, so create two folders called storage and app in the k8s folder.



We now proceed with the configurations for the Sakila database. In the storage folder, we will create two YAML files - sakila-deployment.yml and sakila-service.yml. The sakila-deployment.yml file will store our deployment configuration for the Sakila database. As this is not a Kubernetes tutorial we will only be providing the final configurations. This is what the sakila-deployment.yml file should look like in the end:


apiVersion: apps/v1
kind: Deployment
metadata:
  name: sakila
  labels:
    storage: sakila
spec:
  replicas: 1
  selector:
    matchLabels:
      storage: sakila
  template:
    metadata:
      labels:
        storage: sakila
    spec:
      containers:
      - name: sakila
        image: restsql/mysql-sakila
        ports:
        - containerPort: 3306

And this is the final sakila-service.yml file:

apiVersion: v1
kind: Service
metadata:
  name: sakila
  labels:
    storage: sakila
spec:
  selector:
    storage: sakila
  ports:
  - name: database
    port: 3306
    targetPort: 3306

The deployment and service configurations for our microservice are nearly identical. In the app folder, create a YAML file called speedment-spring-app-deployment.yml with the following contents:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: speedment-spring-app
  labels:
    app: speedment-spring-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: speedment-spring-app
  template:
    metadata:
      labels:
        app: speedment-spring-app
    spec:
      containers:
      - name: speedment-spring-app
        image: speedment-spring-app-example
        ports:
        - containerPort: 8080

In the same folder create another YAML file called speedment-spring-app-service.yml with the following contents:

apiVersion: v1
kind: Service

metadata:
  name: speedment-spring-app
spec:
  selector:
    app: speedment-spring-app
  ports:
  - name: http
    port: 8080
    targetPort: 8080
  type: NodePort

These are all of the configurations we need in order to deploy our database and application. After adding the deployment configurations, our file structure should look like this:


Starting the Cluster

We are nearly done with the preparations for the deployment. There is one last thing we need to do - start our local Kubernetes cluster. This is done by executing the following command:

minikube start


The Deployment

In order to deploy our database and application we will be using Skaffold. In the root of your project create a file called skaffold.yml with the following contents:


apiVersion: skaffold/v2alpha3
kind: Config
build:
  artifacts:
  - image: speedment-spring-app-example
    docker:
      dockerfile: Dockerfile
deploy:
  kubectl:
    manifests:
    - k8s/app/*
    - k8s/storage/*

With this file completed, we are finally ready for deployment. From the project root, execute the following command:

skaffold dev --port-forward=true


When we execute this command, two things will happen:

  1. A Docker image will be created from the Dockerfile we created earlier
  2. Deployments and services will be created from the configurations we created earlier

Once your microservice starts up, you can use it the same way you used it earlier. The only difference now is that it is running from a Kubernetes cluster.

Note: It takes around 30-60 seconds for the Sakila database to boot up completely. Since our application starts a lot quicker than the Sakila database, it will most likely crash and restart a couple of times before the database is ready.

Summary

Creating applications in a time-efficient manner can sometimes be hard. We have explained how to generate a microservice from a database and deploy it to a Kubernetes cluster, so hopefully, you’ve learned something that will reduce your development time.

We hope you’ve enjoyed reading this article as much as we enjoyed writing it. The final version of the source code from this article can be found here.

Authors

Per Minborg
Mislav Miličević

Resources

The Speedment Initializer capable of generating project templates
Speedment OpenSource on GitHub
Speedment Online Manual
Github Repository with the final version of the source code



Tuesday, December 10, 2019

Java/Spring: How to Generate an Entire Database CRUD REST API with Speedment


As each year passes it is becoming nothing but obvious that the Spring Framework is one of the most widely used web development frameworks for Java. With the next decade just around the corner, Spring’s most popular module, Spring Boot, has just received a major update.

The new Spring Boot version "2.2.0" and the year "2020" are almost a perfect match. Thus, the Speedment team has now filled the gap by revamping the Spring Boot plugin.

If this is your first time hearing of Speedment, you’re in for a treat, as we will be demonstrating how the Speedment Spring Boot plugin allows developers to effortlessly build Spring database applications with Speedment, an ORM with a powerful Stream-based query API, as its backbone.

About Speedment

Speedment can be described as an ORM that the Java community deserves - a toolkit for those who like fast development and even faster applications. By leveraging the Java Stream API as its primary means of communication with your database of choice, Speedment makes developers with previous Java experience feel right at home. Alongside the easy-to-use API, Speedment provides developers with a graphical tool that generates the domain model for them in a matter of seconds.

If you’re interested in Speedment as a whole, detailed documentation with examples can be found here. The rest of this article will focus on the Spring Boot plugin.

Spring Boot: The Quickest Start 

Speedment Spring Boot plugin has been around for a while, but starting with Speedment 3.2.2 a major feature was introduced - the ability to generate an entire CRUD REST API directly from your database model.

Depending on whether you’re starting from scratch or have an existing project, the steps will differ, but rest assured that the integration process is effortless regardless of the state of your project.

If you wish to integrate Spring Boot into an existing Speedment project, you are required to add the following 2 clauses to your pom.xml:

<plugin>
    <groupId>com.speedment.enterprise</groupId>
    <artifactId>speedment-enterprise-maven-plugin</artifactId>
    <version>${speedment.version}</version>
                
    <configuration>
        <components>
            <component>com.speedment.enterprise.plugins.spring.SpringGeneratorBundle</component>
        </components>
        <appName>${project.artifactId}</appName>
        <packageName>${project.groupId}</packageName>
    </configuration>
    ... // Database connector dependency           
</plugin>
<dependencies>
 ...
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.speedment.enterprise.plugins</groupId>
    <artifactId>spring-runtime</artifactId>
    <version>${speedment.version}</version>
</dependency>
...
</dependencies>

Once added, the next time you regenerate your domain model, a Speedment-specific Spring configuration should get generated. The generated configuration handles database connection properties and bean registrations for various managers generated by Speedment.

If you’re starting from scratch, head over to the project initializer where a Spring-Boot-ready project will be generated for you. How you will configure the project is up to you, but to include the Spring Boot plugin in the generated project, make sure that the checkbox next to Spring in the Plugins section is checked. Once you’re satisfied with the project configuration, click on the Download button and you will receive a zipped-up project ready for use.


CRUD Made Easy

Once you install the plugin, some Spring Boot specific options will be available in the Speedment tool which can be used to configure your REST API. You can launch the Speedment tool by issuing the following command:
mvn speedment:tool

If this is your first time using Speedment, you may want to familiarize yourself with the workflow by following the “Hello Speedment” quick start guide.

By default, the Speedment tool won’t generate a REST API. To generate a CRUD REST API for a specific table, select the table in the tree view and check the “Generate @RestController” option along with the “REST Enable Create/Update/Delete” option. By clicking “Generate”, a set of REST mappings that implement CRUD operations for a specific table will get generated.



That’s it! No manual coding is needed. Just start the generated Spring by issuing the command:
mvn spring-boot:run

Creating Entities Using REST 

To create a new entity using your generated REST API, you must execute a POST request to the route specified in the tool. By default, the name of this route is the same as the name of your table, prefixed by the name of your schema. If you uncheck the “REST Endpoint” option, you may specify a custom route name. The request body should contain key-value pairs in a JSON object where “REST Field Name” values from the tool are keys.

If we were to have a table called ‘person’ with the columns ‘id’, ‘name’, and ‘age’, we would send the following request to create a new ‘person’ entity:

POST localhost:8080/db/person
{
    “id”: 1,
    “name”: “Jane”,
    “age”: 25
}

curl -d '{“id”: 1,“name”: “Jane”,“age”: 25}' -H "Content-Type:application/json" -X POST localhost:8080/db/person

If a column is auto-generated (or is using a sequence), you may exclude it from the POST body. If you wish to enforce the exclusion of a certain column from the POST body, click on the specific column in the tool tree view and uncheck “Include in Create Body” and regenerate your domain model. On the other hand, if you want to enforce that a certain column is present in the POST body when a request is executed, check “Required in Create Body” and regenerate your domain model.



Retrieving Entities Using REST


To retrieve our newly created entity, we must execute a GET request on the same path used for entity creation:

GET localhost:8080/db/person

curl localhost:8080/db/person/1


The executed request will return a JSON Array of all existing entities. In our case, it would return an array with just our only entity:

[
    {
        “id”: 1,
        “name”: “Jane”,
        “age”: 25
    }
]
Advanced concepts such as filters and sorters are covered in great detail in the official Speedment documentation.

Updating Existing Entities Using REST 

Updating an existing entity using your REST API is done in a similar fashion as creating an entity. Instead of a POST request, we execute a PATCH request and the route is extended by an entity identifier. What our entity identifier depends on the Primary Key column of that table. Since our PK column is a numeral type, our entity identifier will be an integer.

To update the entity we created in our previous example, we would execute the following request:

PATCH localhost:8080/db/person/1
{
    “name”: “Mike”,
    “age”: 43
}

curl -d '{“name”: “Jane”,“age”: 25}' -H "Content-Type:application/json" -X PATCH localhost:8080/db/person/1
By default, all columns are included in the PATCH body (except the Primary Key column), but they are not mandatory. If you wish to enforce the exclusion of a certain column from your request body, click on the specific column in the tool tree view and uncheck “Include in Update Body” and regenerate your domain model. On the other hand, if you want to enforce column presence in the request body, check “Required in Update Body” and regenerate your domain model.


Deleting entities using REST

Deleting an entity using your REST API is quite straightforward - we execute a DELETE request on the same path used for entity updates.

To delete the entity we’ve created and updated in the previous examples, we would execute the following request:


DELETE localhost:8080/db/person/1

curl -X DELETE localhost:8080/db/person/1

Summary

Starting new projects can sometimes be a hustle. As developers, we want to avoid these inconveniences as much as possible and dive straight into coding. With Speedment's new Spring Boot plugin, developers can get ahead of the game by automatically generating all necessary configurations and REST controllers directly from the database.

We hope you’ve enjoyed this brief guide to the new CRUD features the Speedment Spring Boot plugin provides. If you’re interested in a more detailed explanation of the new features, head over to the official documentation where you will find in-depth explanations and examples of the new CRUD features.

Authors

Per Minborg
Mislav Miličević