Book Image

Spring: Microservices with Spring Boot

By : In28Minutes Official
Book Image

Spring: Microservices with Spring Boot

By: In28Minutes Official

Overview of this book

Microservices helps in decomposing applications into small services and move away from a single monolithic artifact. It helps in building systems that are scalable, flexible, and high resilient. Spring Boot helps in building REST-oriented, production-grade microservices. This book is a quick learning guide on how to build, monitor, and deploy microservices with Spring Boot. You'll be first familiarized with Spring Boot before delving into building microservices. You will learn how to document your microservice with the help of Spring REST docs and Swagger documentation. You will then learn how to secure your microservice with Spring Security and OAuth2. You will deploy your app using a self-contained HTTP server and also learn to monitor a microservice with the help of Spring Boot actuator. This book is ideal for Java developers who knows the basics of Spring programming and want to build microservices with Spring Boot. This book is embedded with useful assessments that will help you revise the concepts you have learned in this book. This book is repurposed for this specific learning experience from material from Packt's Mastering Spring 5.0 by Ranga Rao Karanam.
Table of Contents (7 chapters)

Spring Boot Hello World


We will start with building our first Spring Boot application in this lesson. We will use Maven to manage dependencies.

The following steps are involved in starting up with a Spring Boot application:

  1. Configure spring-boot-starter-parent in your pom.xml file.

  2. Configure the pom.xml file with the required starter projects.

  3. Configure spring-boot-maven-plugin to be able to run the application.

  4. Create your first Spring Boot launch class.

Let's start with step 1, configuring the starter projects.

Configure spring-boot-starter-parent

Let's start with a simple pom.xml file with spring-boot-starter-parent:

    <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.mastering.spring</groupId> 
    <artifactId>springboot-example</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <name>First Spring Boot Example</name> 
    <packaging>war</packaging>
    <parent> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-parent</artifactId>  
      <version>2.0.0.M1</version>
    </parent>
    <properties> 
      <java.version>1.8</java.version> 
    </properties>

   <repositories>
    <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
   </repositories>

   <pluginRepositories>
    <pluginRepository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/milestone</url>
        <snapshots>
          <enabled>false</enabled>
        </snapshots>
     </pluginRepository>
    </pluginRepositories>

</project>

The first question is this: why do we need spring-boot-starter-parent?

A spring-boot-starter-parent dependency contains the default versions of Java to use, the default versions of dependencies that Spring Boot uses, and the default configuration of the Maven plugins.

Note

The spring-boot-starter-parent dependency is the parent POM providing dependency and plugin management for Spring Boot-based applications.

Let's look at some of the code inside spring-boot-starter-parent to get a deeper understanding about spring-boot-starter-parent.

spring-boot-starter-parent

The spring-boot-starter-parent dependency inherits from spring-boot-dependencies, which is defined at the top of the POM. The following code snippet shows an extract from spring-boot-starter-parent:

    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.0.0.M1</version>
      <relativePath>../../spring-boot-dependencies</relativePath>
   </parent>

The spring-boot-dependencies provides default dependency management for all the dependencies that Spring Boot uses. The following code shows the different versions of various dependencies that are configured in spring-boot-dependencies:

<activemq.version>5.13.4</activemq.version>
<aspectj.version>1.8.9</aspectj.version>
<ehcache.version>2.10.2.2.21</ehcache.version>
<elasticsearch.version>2.3.4</elasticsearch.version>
<gson.version>2.7</gson.version>
<h2.version>1.4.192</h2.version>
<hazelcast.version>3.6.4</hazelcast.version>
<hibernate.version>5.0.9.Final</hibernate.version>
<hibernate-validator.version>5.2.4.Final</hibernate
  validator.version>
<hsqldb.version>2.3.3</hsqldb.version>
<htmlunit.version>2.21</htmlunit.version>
<jackson.version>2.8.1</jackson.version>
<jersey.version>2.23.1</jersey.version>
<jetty.version>9.3.11.v20160721</jetty.version>
<junit.version>4.12</junit.version>
<mockito.version>1.10.19</mockito.version>
<selenium.version>2.53.1</selenium.version>
<servlet-api.version>3.1.0</servlet-api.version>
<spring.version>4.3.2.RELEASE</spring.version>
<spring-amqp.version>1.6.1.RELEASE</spring-amqp.version>
<spring-batch.version>3.0.7.RELEASE</spring-batch.version>
<spring-data-releasetrain.version>Hopper-SR2</spring-
  data-releasetrain.version>
<spring-hateoas.version>0.20.0.RELEASE</spring-hateoas.version>
<spring-restdocs.version>1.1.1.RELEASE</spring-restdocs.version>
<spring-security.version>4.1.1.RELEASE</spring-security.version>
<spring-session.version>1.2.1.RELEASE</spring-session.version>
<spring-ws.version>2.3.0.RELEASE</spring-ws.version>
<thymeleaf.version>2.1.5.RELEASE</thymeleaf.version>
<tomcat.version>8.5.4</tomcat.version>
<xml-apis.version>1.4.01</xml-apis.version>

If we want to override a specific version of a dependency, we can do that by providing a property with the right name in the pom.xml file of our application. The following code snippet shows an example of configuring our application to use version 1.10.20 of Mockito:

    <properties>
     <mockito.version>1.10.20</mockito.version>
    </properties>

The following are some of the other things defined in spring-boot-starter-parent:

  • The default Java version<java.version>1.8</java.version>

  • The default configuration for Maven plugins:

    • maven-failsafe-plugin

    • maven-surefire-plugin

    • git-commit-id-plugin

Compatibility between different versions of frameworks is one of the major problems faced by developers. How do I find the latest Spring Session version that is compatible with a specific version of Spring? The usual answer would be to read the documentation. However, if we use Spring Boot, this is made simple by spring-boot-starter-parent. If we want to upgrade to a newer Spring version, all that we need to do is to find the spring-boot-starter-parentdependency for that Spring version. Once we upgrade our application to use that specific version of spring-boot-starter-parent, we would have all the other dependencies upgraded to the versions compatible with the new Spring version. One less problem for developers to handle. Always make me happy.

Configure pom.xml with the Required Starter Projects

Whenever we want to build an application in Spring Boot, we would need to start looking for starter projects. Let's focus on understanding what a starter project is.

Understanding Starter Projects

Starters are simplified dependency descriptors customized for different purposes. For example, spring-boot-starter-web is the starter for building web application, including RESTful, using Spring MVC. It uses Tomcat as the default embedded container. If I want to develop a web application using Spring MVC, all we would need to do is include spring-boot-starter-web in our dependencies, and we get the following automatically pre-configured:

  • Spring MVC

  • Compatible versions of jackson-databind (for binding) and hibernate-validator (for form validation)

  • spring-boot-starter-tomcat (starter project for Tomcat)

The following code snippet shows some of the dependencies configured in spring-boot-starter-web:

    <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
       </dependency>
    </dependencies>

As we can see in the preceding snippet, when we usespring-boot-starter-web, we get a lot of frameworks auto-configured.

For the web application we would like to build, we would also want to do some good unit testing and deploy it on Tomcat. The following snippet shows the different starter dependencies that we would need. We would need to add this to our pom.xml file:

    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-tomcat</artifactId>
       <scope>provided</scope>
     </dependency>
    </dependencies>

We add three starter projects:

  • We've already discussed spring-boot-starter-web. It provides us with the frameworks needed to build a web application with Spring MVC.

  • The spring-boot-starter-test dependency provides the following test frameworks needed for unit testing:

    • JUnit: Basic unit test framework

    • Mockito: For mocking

    • Hamcrest, AssertJ: For readable asserts

    • Spring Test: A unit testing framework for spring-context based applications

  • The spring-boot-starter-tomcat dependency is the default for running web applications. We include it for clarity. The spring-boot-starter-tomcat is the starter for using Tomcat as the embedded servlet container.

We now have our pom.xml file configured with the starter parent and the required starter projects. Let's add spring-boot-maven-plugin now, which would enable us to run Spring Boot applications.

Configuring spring-boot-maven-plugin

When we build applications using Spring Boot, there are a couple of situations that are possible:

  • We would want to run the applications in place without building a JAR or a WAR

  • We would want to build a JAR and a WAR for later deployment

The spring-boot-maven-plugin dependency provides capabilities for both of the preceding situations. The following snippet shows how we can configure spring-boot-maven-plugin in an application:

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

The spring-boot-maven-plugin dependency provides several goals for a Spring Boot application. The most popular goal is run (this can be executed as mvn spring-boot:run on the command prompt from the root folder of the project).

Creating Your First Spring Boot Launch Class

The following class explains how to create a simple Spring Boot launch class. It uses the static run method from the SpringApplication class, as shown in the following code snippet:

    package com.mastering.spring.springboot;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot
    autoconfigure.SpringBootApplication;
    import org.springframework.context.ApplicationContext;
    @SpringBootApplication public class Application {
       public static void main(String[] args)
        { 
         ApplicationContext ctx = SpringApplication.run
         (Application.class,args);
        }
     }

The preceding code is a simple Java main method executing the static run method on the SpringApplication class.

The SpringApplication Class

The SpringApplication class can be used to Bootstrap and launch a Spring application from a Java main method.

The following are the steps that are typically performed when a Spring Boot application is bootstrapped:

  1. Create an instance of Spring's ApplicationContext.

  2. Enable the functionality to accept command-line arguments and expose them as Spring properties.

  3. Load all the Spring beans as per the configuration.

The @SpringBootApplication Annotation

The @SpringBootApplication annotation is a shortcut for three annotations:

  • @Configuration: Indicates that this a Spring application context configuration file.

  • @EnableAutoConfiguration: Enables auto-configuration, an important feature of Spring Boot. We will discuss auto-configuration later in a separate section.

  • @ComponentScan: Enables scanning for Spring beans in the package of this class and all its sub packages.

Running Our Hello World Application

We can run the Hello World application in multiple ways. Let's start running it with the simplest option--running as a Java application. In your IDE, right-click on the application class and run it as Java Application. The following screenshot shows some of the log from running our Hello World application:

The following are the key things to note:

  • Tomcat server is launched on port 8080--Tomcat started on port(s): 8080 (http).

  • DispatcherServlet is configured. This means that Spring MVC Framework is ready to accept requests--Mapping servlet: 'dispatcherServlet' to [/].

  • Four filters--characterEncodingFilter, hiddenHttpMethodFilter, httpPutFormContentFilter and requestContextFilter--are enabled by default

  • The default error page is configured--Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)

  • WebJars are autoconfigured. WebJars enable dependency management for static dependencies such as Bootstrap and query--Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]

The following screenshot shows the application layout as of now. We have just two files, pom.xml and Application.java:

With a simple pom.xml file and one Java class, we were able to get to launch the Spring MVC application, with all the preceding functionality described. The most important thing about Spring Boot is to understand what happens in the background. Understanding the preceding start up log is the first. Let's look at the Maven dependencies to get a deeper picture.

The following screenshot shows some of the dependencies that are configured with the basic configuration in the pom.xml file that we created:

Spring Boot does a lot of magic. Once you have the application configured and running, I recommend that you play around with it to gain a deeper understanding that will be useful when you are debugging problems.

As Spiderman says, with great power, comes great responsibility. This is absolutely true in the case of Spring Boot. In the time to come, the best developers with Spring Boot would be the ones who understand what happens in the background--dependencies and auto-configuration.

Auto-configuration

To enable us to understand auto-configuration further, let's expand our application class to include a few more lines of code:

    ApplicationContext ctx = SpringApplication.run(Application.class,
     args);
    String[] beanNames = ctx.getBeanDefinitionNames();
    Arrays.sort(beanNames);

   for (String beanName : beanNames) {
     System.out.println(beanName);
    }

We get all the beans that are defined in the Spring application context and print their names. When Application.java is run as a Java program, it prints the list of beans, as shown in the following output:

application
basicErrorController
beanNameHandlerMapping
beanNameViewResolver
characterEncodingFilter
conventionErrorViewResolver
defaultServletHandlerMapping
defaultViewResolver
dispatcherServlet
dispatcherServletRegistration
duplicateServerPropertiesDetector
embeddedServletContainerCustomizerBeanPostProcessor
error
errorAttributes
errorPageCustomizer
errorPageRegistrarBeanPostProcessor
faviconHandlerMapping
faviconRequestHandler
handlerExceptionResolver
hiddenHttpMethodFilter
httpPutFormContentFilter
httpRequestHandlerAdapter
jacksonObjectMapper
jacksonObjectMapperBuilder
jsonComponentModule
localeCharsetMappingsCustomizer
mappingJackson2HttpMessageConverter
mbeanExporter
mbeanServer
messageConverters
multipartConfigElement
multipartResolver
mvcContentNegotiationManager
mvcConversionService
mvcPathMatcher
mvcResourceUrlProvider
mvcUriComponentsContributor
mvcUrlPathHelper
mvcValidator
mvcViewResolver
objectNamingStrategy
autoconfigure.AutoConfigurationPackages
autoconfigure.PropertyPlaceholderAutoConfiguration
autoconfigure.condition.BeanTypeRegistry
autoconfigure.context.ConfigurationPropertiesAutoConfiguration
autoconfigure.info.ProjectInfoAutoConfiguration
autoconfigure.internalCachingMetadataReaderFactory
autoconfigure.jackson.JacksonAutoConfiguration
autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration
autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration
autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration
autoconfigure.jmx.JmxAutoConfiguration
autoconfigure.web.DispatcherServletAutoConfiguration
autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletConfiguration
autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration
autoconfigure.web.EmbeddedServletContainerAutoConfiguration
autoconfigure.web.EmbeddedServletContainerAutoConfiguration$EmbeddedTomcat
autoconfigure.web.ErrorMvcAutoConfiguration
autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration
autoconfigure.web.HttpEncodingAutoConfiguration
autoconfigure.web.HttpMessageConvertersAutoConfiguration
autoconfigure.web.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration
autoconfigure.web.JacksonHttpMessageConvertersConfiguration
autoconfigure.web.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration
autoconfigure.web.MultipartAutoConfiguration
autoconfigure.web.ServerPropertiesAutoConfiguration
autoconfigure.web.WebClientAutoConfiguration
autoconfigure.web.WebClientAutoConfiguration$RestTemplateConfiguration
autoconfigure.web.WebMvcAutoConfiguration
autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration
autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter
autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration
autoconfigure.websocket.WebSocketAutoConfiguration
autoconfigure.websocket.WebSocketAutoConfiguration$TomcatWebSocketConfiguration
context.properties.ConfigurationPropertiesBindingPostProcessor
context.properties.ConfigurationPropertiesBindingPostProcessor.store
annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
annotation.ConfigurationClassPostProcessor.importAwareProcessor
annotation.internalAutowiredAnnotationProcessor
annotation.internalCommonAnnotationProcessor
annotation.internalConfigurationAnnotationProcessor
annotation.internalRequiredAnnotationProcessor
event.internalEventListenerFactory
event.internalEventListenerProcessor
preserveErrorControllerTargetClassPostProcessor
propertySourcesPlaceholderConfigurer
requestContextFilter
requestMappingHandlerAdapter
requestMappingHandlerMapping
resourceHandlerMapping
restTemplateBuilder
serverProperties
simpleControllerHandlerAdapter
spring.http.encoding-autoconfigure.web.HttpEncodingProperties
spring.http.multipart-autoconfigure.web.MultipartProperties
spring.info-autoconfigure.info.ProjectInfoProperties
spring.jackson-autoconfigure.jackson.JacksonProperties
spring.mvc-autoconfigure.web.WebMvcProperties
spring.resources-autoconfigure.web.ResourceProperties
standardJacksonObjectMapperBuilderCustomizer
stringHttpMessageConverter
tomcatEmbeddedServletContainerFactory
viewControllerHandlerMapping
viewResolver
websocketContainerCustomizer

Important things to think about are as follows:

  • Where are these beans defined?

  • How are these beans created?

That's the magic of Spring auto-configuration.

Whenever we add a new dependency to a Spring Boot project, Spring Boot auto-configuration automatically tries to configure the beans based on the dependency.

For example, when we add a dependency in spring-boot-starter-web, the following beans are auto-configured:

  • basicErrorController, handlerExceptionResolver: It is the basic exception handling. It shows a default error page when an exception occurs.

  • beanNameHandlerMapping: It is used to resolve paths to a handler (controller).

  • characterEncodingFilter: It provides default character encoding UTF-8.

  • dispatcherServlet: It is the front controller in Spring MVC applications.

  • jacksonObjectMapper: It translates objects to JSON and JSON to objects in REST services.

  • messageConverters: It is the default message converters to convert from objects into XML or JSON and vice versa.

  • multipartResolver: It provides support to upload files in web applications.

  • mvcValidator: It supports validation of HTTP requests.

  • viewResolver: It resolves a logical view name to a physical view.

  • propertySourcesPlaceholderConfigurer: It supports the externalization of application configuration.

  • requestContextFilter: It defaults the filter for requests.

  • restTemplateBuilder: It is used to make calls to REST services.

  • tomcatEmbeddedServletContainerFactory: Tomcat is the default embedded servlet container for Spring Boot-based web applications.

In the next section, let's look at some of the starter projects and the auto-configuration they provide.

Starter Projects

The following table shows some of the important starter projects provided by Spring Boot:

Starter

Description

spring-boot-starter-webservices

This is a starter project to develop XMLbased web services.

spring-boot-starter-web

This is a starter project to build Spring MVC-based web applications or RESTful applications. It uses Tomcat as the default embedded servlet container.

spring-boot-starter-activemq

This supports message-based communication using JMS on ActiveMQ.

spring-boot-starterintegration

This supports the Spring Integration Framework that provides implementations for Enterprise Integration Patterns.

spring-boot-starter-test

This provides support for various unit testing frameworks, such as JUnit, Mockito, and Hamcrest matchers.

spring-boot-starter-jdbc

This provides support for using Spring JDBC. It configures a Tomcat JDBC connection pool by default.

spring-boot-startervalidation

This provides support for the Java Bean Validation API. Its default implementation is hibernate-validator.

spring-boot-starter-hateoas

HATEOAS stands for Hypermedia as the Engine of Application State. RESTful services that use HATEOAS return links to additional resources that are related to the current context in addition to data.

spring-boot-starter-jersey

JAX-RS is the Java EE standard to develop REST APIs. Jersey is the default implementation. This starter project provides support to build JAX-RS-based REST APIs.

spring-boot-starterwebsocket

HTTP is stateless. WebSockets allow you to maintain a connection between the server and the browser. This starter project provides support for Spring WebSockets.

spring-boot-starter-aop

This provides support for Aspect Oriented Programming. It also provides support for AspectJ for advanced aspect-oriented programming.

spring-boot-starter-amqp

With RabbitMQ as the default, this starter project provides message passing with AMQP.

spring-boot-starter-security

This starter project enables auto-configuration for Spring Security.

spring-boot-starter-data-jpa

This provides support for Spring Data JPA. Its default implementation is Hibernate.

spring-boot-starter

This is a base starter for Spring Boot applications. It provides support for auto-configuration and logging.

spring-boot-starter-batch

This provides support to develop batch applications using Spring Batch.

spring-boot-starter-cache

This is the basic support for caching using Spring Framework.

spring-boot-starter-datarest

This is the support to expose REST services using Spring Data REST.

Until now, we have set up a basic web application and understood some of the important concepts related to Spring Boot:

  • Auto-configuration

  • Starter projects

  • spring-boot-maven-plugin

  • spring-boot-starter-parent

  • Annotation @SpringBootApplication

Now let's shift our focus to understanding what REST is and building a REST Service.