First microservice with Spring Boot

The following are the details of the microservice that we are going to develop:

  • We will implement an accounting service as a microservice.
  • The microservice will be REST-based. It is an architectural pattern for developing web services. It focuses on identifying each resource in the application with a unique URL.
  • We will identify the Spring Boot starter project that we will need and generate the Maven pom.xml file accordingly.
  • We will implement an Account class with a few basic properties.
  • We will implement AccountRepository with the find-by-name example method.
  • We will implement the controller class, which has a repository auto-wired. The controller exposes the endpoints.
  • We will also implement a way to feed the test data into the database.

Let's start!

We will start implementation by generating the Spring Boot application using Spring Initializr. We have to decide on the Spring Boot starter projects to be used. We want to develop a JPA-based web application. For the purpose of storing Account data in a database, we can use either MySQL or H2. Usually, H2 is a more convenient option as we don't need to set up anything. We will use MySQL for the examples in this chapter.

The following are the starter projects to be selected:

  • Web
  • JPA
  • MySQL or H2
  • REST repositories

We can also add the Spring Boot Actuator for application monitoring purpose but is not mandatory for the example.

The following is the pom.xml file that is generated by Spring Initializr:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.packt.springhighperformance.ch09</groupId>
<artifactId>ch-09-accounting-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>accounting-service</name>
<description>Example accounting service</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Another piece of code that is generated by Spring Initializr is the Spring Boot application:

package com.packt.springhighperformance.ch09.accountingservice;

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

@SpringBootApplication
public class AccountingServiceApplication {

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

At this point, we should have our project imported in our IDE of preference.

People, get ready for the hands-on development now. We will start by creating the Account JPA entity class. We will annotate the Account class with @Entity and @Table annotations. The @Table annotation allows us to supply the desired table name. We have one more column, which is accountName. It stores and represents the name of the Account. Basically, the Account entity represents the account type in the real world. One other important attribute that we have added is id. id represents a unique, autogenerated numeric identifier. We can identify each account uniquely using the identifier. The @GeneratedValue annotation lets us supply the way id values will be generated in the database. Keeping it to AUTO defines that it depends on the database to automatically generate id values. The @Column annotation allows us to match the accountName attribute to the ACCT_NAME database field.

The following is the code for the Account entity:

package com.packt.springhighperformance.ch09.accountingservice.models;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "accounts")
public class Account {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ACCT_ID")
private Long id;

@Column(name = "ACCT_NAME")
private String accountName;

public Account() {
}

public Account(String accountName) {
this.accountName = accountName;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getAccountName() {
return accountName;
}

public void setAccountName(String accountName) {
this.accountName = accountName;
}

@Override
public String toString() {
return "Account{"
+ "id=" + id +
", accountName='" + accountName + ''' +
'}';
}

}

Spring Data provides a convenient interface to perform common database operations. The interface is called CrudRepository. It supports basic Create, Read, Update, and Delete operations for a specific type. The interface is inherited by the JpaRepository interface, which is a JPA-specific definition of the CrudRepository interface. JpaRepository also inherits sorting and paging capabilities from the PagingAndSortingRepository interface.

With this background, the next task for us is to build an interface to interact with the accounts database table. The following is the code for the AccountsRepository class:

package com.packt.springhighperformance.ch09.
accountingservice.repositories;

import java.util.Collection;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

import com.packt.springhighperformance.ch09.accountingservice.models.Account;

@RepositoryRestResource
public interface AccountsRepository extends JpaRepository<Account, Long> {

Collection<Account> findByAccountName(@Param("an") String an);
}

In the AccountsRepository interface, we have defined a method that is intended to find the Account entries from the database based on the accountName. The CrudRepository interface is very powerful. It will generate the implementation for the findByAccountName method. It can generate the implementation for all such query methods that follow the convention, such as findBy{model-attribute-name}. It also returns the objects of the Account type.

Also, you might have noticed that the use of @RepositoryRestResource is provided by the Spring Data REST module. It briefly exposes the repository methods for data manipulation as REST endpoints without any further configuration or development.

Now, we have the entity and repository in place. Next is the controller part of a web application. We have to create a controller class. The following is the code for the AccountsController class:

package com.packt.springhighperformance.ch09
.accountingservice.controllers;

import java.util.Collections;
import java.util.Map;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AccountsController {
@GetMapping(value = "/account/{name}")
Map<String, Object> getAccount(@PathVariable String name) {
return Collections.singletonMap("Account : ", name);
}
}

Three notable annotations from the AccountsController code are:

  • @RestController: This annotation is a combination of the @Controller and @ResponseBody annotations. If we used the @RestController annotation, we don't need to define these two other annotations. The @RestController annotation indicates that the class should be treated as a controller and every endpoint method will respond with content as a response body.
  • @GetMapping: This annotation is used to define a REST GET endpoint mapping.
  • @PathVariable: This annotation is used to fetch the values supplied in the URL path itself.

Two things are left. One is the database and other important properties, while the other one is a way to populate the initial data in the accounts table.

The following is the application.properties file that manages the configuration part of the application:

spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.url=jdbc:mysql://localhost:3306/db_example?useSSL=false
spring.datasource.username=root
spring.datasource.password=root

From the list of properties, the spring.jpa.hibernate.ddl-auto property determines the initial generation of the database based on the database configurations provided. It determines whether the Spring Boot application should create the database schema up on application startup. none, validate, update, create, and create-drop are the options available for the property.

While booting up the application, we may also receive the following error:

Establishing SSL connection without server's identity verification is not recommended.

We can use useSSL=true in the database connection URL to overcome this warning, as you can see in the properties in the preceding code example.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset