Monday, September 18, 2017

Auto-Restart Spring Boot Application On Code Change With Dev Tools

Spring Boot Dev Tools enables auto-restarting a Spring boot application whenever any class is changed in the class path. This is not comparable in speed with the hot swap functionality offered by Jrebel or Spring Loaded, but this is a very simple and easy way to implement and better than manual restart. In this post, I use a simple Spring boot rest echo service to demonstrate how spring boot dev tools can be used to auto restart the application when using Maven on an IDE or Gradle from command line. In either options, the main trigger for a restart is the change to a class file, which means that the change to a Java file has to be compiled either by the IDE in option 1 or by Gradle in option 2. The only thing that you have to do from the application is to add a dependency to spring boot dev tools

Maven

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-devtools</artifactId>
 <scope>runtime</scope>
</dependency>

Gradle

runtime('org.springframework.boot:spring-boot-devtools')
For this example, I am using a simple Spring Boot application created by Spring Initializr, and add the following Java class as a simple echo service
package com.aoj.springdevtools;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EchoService {

 @RequestMapping("/echo")
 public String greeting(@RequestParam(value = "name") String name) {
  return "Hello1 : " + name;
 }
}

With Maven and Eclipse

Once you get the project from Spring Initializr, import it as a Maven project. And add the Java class to the source. From eclipse, use "Run as Java application" to run the Spring boot application, and it will start the application. Any code changes you made will be automatically compiled by Eclpise and Spring boot will restart the appliation automatically.

With Gradle

Gradle provides a continuous build option, which keep track of the source folders and triggers a build whenever the source is changed. The automatic build by Gradle, in turn, trigger the restart of the Spring boot application. To see this in action you will need two command-line windows.
  1. In the first window start the gradle continuous build with the following command
    gradlew build --continuous
  2. In the second window, run the spring boot application with the command
    gradle bootRun
Once you are done with these steps, if you change your source file, you will notice that a build is triggered in the first window, following which, a restart of spring boot application can be seen in the second window. Here is the source code for the project

build.gradle

buildscript {
 ext {
  springBootVersion = '2.0.0.M4'
 }
 repositories {
  mavenCentral()
  maven { url "https://repo.spring.io/snapshot" }
  maven { url "https://repo.spring.io/milestone" }
 }
 dependencies {
  classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
 }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.aoj'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
 mavenCentral()
 maven { url "https://repo.spring.io/snapshot" }
 maven { url "https://repo.spring.io/milestone" }
}


dependencies {
 compile('org.springframework.boot:spring-boot-starter-web')
 runtime('org.springframework.boot:spring-boot-devtools')
 testCompile('org.springframework.boot:spring-boot-starter-test')
}

pom.xml

<?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.aoj</groupId>
 <artifactId>spring-devtools</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>spring-devtools</name>
 <description>Demo project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.0.M4</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-web</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-devtools</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>

 <repositories>
  <repository>
   <id>spring-snapshots</id>
   <name>Spring Snapshots</name>
   <url>https://repo.spring.io/snapshot</url>
   <snapshots>
    <enabled>true</enabled>
   </snapshots>
  </repository>
  <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-snapshots</id>
   <name>Spring Snapshots</name>
   <url>https://repo.spring.io/snapshot</url>
   <snapshots>
    <enabled>true</enabled>
   </snapshots>
  </pluginRepository>
  <pluginRepository>
   <id>spring-milestones</id>
   <name>Spring Milestones</name>
   <url>https://repo.spring.io/milestone</url>
   <snapshots>
    <enabled>false</enabled>
   </snapshots>
  </pluginRepository>
 </pluginRepositories>


</project>

SpringDevtoolsApplication.java

package com.aoj.springdevtools;

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

@SpringBootApplication
public class SpringDevtoolsApplication {

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

EchoService.java

package com.aoj.springdevtools;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EchoService {

 @RequestMapping("/echo")
 public String greeting(@RequestParam(value = "name") String name) {
  return "Hello1 : " + name;
 }
}

No comments:

Post a Comment

Popular Posts