Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Microservices Using Spring Boot Applications

DZone's Guide to

Microservices Using Spring Boot Applications

Learn how to use Spring Boot to build microservices, which reduces the configuration and boilerplate code you need to write.

· Microservices Zone ·
Free Resource

Containerized Microservices require new monitoring. See why a new APM approach is needed to even see containerized applications.

Spring Boot is based on the Spring Framework and provides the extension configuration on convention model, reducing the need to write a lot of configuration and boilerplate code.

Spring Boot Advantages

  1. It has an opinionated view on Spring Platform and third-party libraries so you can get started with minimum effort and easy to create standalone applications with embedded Tomcat/Jetty/Undertow.

  2. Production-ready services.

  3. Basic health-check and monitoring functions (see the section about Actuator below).

  4. Pre-configured, embedded Tomcat server.

  5. Executable JAR packaging with all dependencies included.

  6. Very little overall configuration overhead (i.e. we just had to configure what we wanted to customize).

Our project involved in the creation of several independent microservices which would provide various functionality for consumers via REST/HTTP APIs and most of them had to communicate with a data store, too. Now each of these services had a single, well-defined function; for example, handling common user data or handling images and videos, hence our goal was to create an independent Spring Boot application which would be an executable jar.

To leverage Spring Boot, we need to set the spring-boot-starter-parent project as your Maven parent (Gradle is supported as well, we used Maven) and put some dependencies in pom.

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

One of the good features in Spring Boot is that it will import default configurations based on the contents of your classpath, so if we want to build a Spring MVC application, we just need to pull spring-boot-starter-web. Thus we don’t have to worry about versions.

The flip side is that when we actually need a specific version of a library, we will have to override these defaults and may encounter incompatibilities

1. Changes in the Spring MVC Service

Step 1: The pom File

The first step in it is to configure Maven for Spring Boot, which means that we need to set our project parent to spring-boot-starter-parent and import spring-boot-starter-web, because this is a web service. We also recommend setting property java.version to 1.7 (it will default to 1.5 otherwise); because Spring Boot is not yet released to production, we will need to set a custom repository (http://repo.spring.io/milestone) to pull all the dependencies:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter</artifactId>
	<exclusions>
		<exclusion>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-logging</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<exclusions>
		<exclusion>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<groupId>org.springframework.boot</groupId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>

Repositories

Plugin repository:

<pluginRepository>
	<id>spring-releases</id>
	<url>https://repo.spring.io/libs-release</url>
</pluginRepository>

Repository:

<repository>
	<id>spring-releases</id>
	<url>https://repo.spring.io/libs-release</url>
</repository>


Step 2: Java Classes

We are going to add two Java classes, one responsible for startup and basic configuration, the other being Servlet Initializer.

Application Class:

package com.cisco.iep.content.application;
import javax.annotation.PostConstruct;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@ImportResource("classpath:/config/xml/spring/content-servlet-context.xml")
@EnableAutoConfiguration
@SpringBootApplication
public class ContentApplication {




 public static void main(String[] args) {


  SpringApplication.run(ContentApplication.class, args);
 }
 @PostConstruct
 public void start() {


 }




}


Servlet Initializer Class (this would be required if we were creating a war file):

package com.cisco.iep.content.application;


import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;


public class ServletInitializer extends SpringBootServletInitializer {


 @Override
 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
  return application.sources(ContentApplication.class);
 }

  
}


Please note the following:

We are here relying on Spring’s annotation and package-scan based approach to configure our controller.

  • @EnableAutoConfiguration --> is specific to Spring Boot and declaring it will result in a lot of pre-defined configuration pulled to our Spring Application Context (like the embedded Tomcat container)

  • @SpringBootApplication --> which is  another Boot-specific component, it’s the default entry point for most of the Spring Boot applications and will take care of the Spring Application Context for us

And that is all you actually need. At this point, we should be able to start this application, which will launch the class ContentApplication. Then visit http://localhost:8080/ which should result in it being displayed in your browser.

Step 3: Packaging the Application

As we have previously mentioned, Spring Boot gives an easy way of packaging applications into a self-contained executable jar file. To do this, just add the spring-boot-maven-plugin build plugin to Maven (we may have to add http://repo.spring.io/milestone as a plugin repository).

Packaging the project should result in the creation of two files, content.jar.original and content.jar. The .original file is the output of the default Maven compiler, while the other one is the jar file enhanced by Spring Boot’s plugin. If we check the sizes, we will notice that the latter one is significantly larger (ours is almost 70 megabytes). The reason for this is that Spring Boot packages all the dependencies necessary to run the application into this single jar executable jar.

If we now start this (simply java -jar), we should see the same output that was in your IDE’s log window.

Step 4: Overriding Default Configuration & Overriding With Command Line Arguments

The fact that Spring Boot pre-configures almost everything that you need for you is very useful when starting the development. However, we would require more control over what is happening in the application very soon. Fortunately, it is quite easy to override these defaults by using property files.

By default, Spring Boot will look for a property file in the package root directory called application.properties; this is a good place to customize your application. By Maven conventions, place this file into the src/main/resources directory so your build artefacts will be generated correctly. For example, let’s set the contents to: server. 

This will cause the embedded Tomcat to listen on port 11000 instead of 8080. If you now restart your service, you should use http://localhost:11000/ to get access.

We also externalized the application.properties and log4j.properties, with the help of maven assembly plugin. We modified execution command by giving application.properties location:

java -jar content.jar  --spring.config.location=/opt/cisco/iep/content/conf/application.properties

 

Step 5: The Spring Boot Actuator

Although this is a slight detour from the general Spring Boot description, when talking about web applications built with it, we cannot leave the Actuator unmentioned. It’s a Spring Boot module that immediately gives your Spring-based web applications basic health check and monitoring interfaces. To use this, we just need to add a Maven dependency: spring-boot-starter-actuator.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-remote-shell</artifactId>
</dependency>


If you now recompile and restart your service, you’ll notice that a lot more endpoints are being mapped (this is printed to the log during startup). Some of these are:

  • /health – returns “ok” as text/plain content which is useful for simple service monitoring

  • /env – check environment configuration, property file and command line argument overrides, active profiles

  • /metrics – basic statistics on your service endpoints (e.g. hit count, error count)

  • /dump – thread dump

  • /trace – the latest HTTP request/response pairs

You can access/modify (or change completely if you wish) the behavior for most of these. We have added HealthIndicator:

          package com.cisco.iep.content.application;


          import org.springframework.stereotype.Component;


          import org.springframework.boot.actuate.health.Health;
          import org.springframework.boot.actuate.health.HealthIndicator;


          @Component
          public class HealthCheck implements HealthIndicator {
           @Override
           public Health health() {
            int errorCode = check(); // perform some specific health check
            if (errorCode != 0) {
             return Health.down().withDetail("Error Code", errorCode).build();
            }
            return Health.up().build();
           }


           public int check() {
            return 0;
           }
          }


Caveats

Although most features that Spring Boot gives you are extremely useful and work very well immediately, we encountered a few cases where a bit of caution is recommended:

Logging

Spring Boot will import and use Logback and SLF4J as default loggers. If you want to use something else (e.g. Log4J) or one of your dependencies transitively imports it, you need to be careful and use the appropriate logger bridges. Some combinations may result in your applications not starting at all. Maven exclusions for transitive dependencies will come handy.

We used Sl4j and log4j-over-slf4j dependencies to resolve the issues.

Current Specification of the Project

  • I removed log4j from all the dependent projects and used sl4j and log4j-over-slf4j dependencies.

  • We are using two data sources in this project:  1) JDBC (bean name: basicDataSource) and 2) C3P0 (bean name: dataSource).

  • I upgraded the version of Spring to 4.2.3 and Spring Boot to 1.3.3. We are using Java 7.

  • Assembly plugin: I added application.properties and log4j.properties as part of content-env.zip.

  • I have added an embedded tomcat plugin.

Automatically manage containers and microservices with better control and performance using Instana APM. Try it for yourself today.

Topics:
spring boot ,microservices ,java ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}