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;
 }
}

1 comment:

  1. The effectiveness of IEEE Project Domains depends very much on the situation in which they are applied. In order to further improve IEEE Final Year Project Domains practices we need to explicitly describe and utilise our knowledge about software domains of software engineering Final Year Project Domains for CSE technologies. This paper suggests a modelling formalism for supporting systematic reuse of software engineering technologies during planning of software projects and improvement programmes in Project Centers in Chennai for CSE.

    Spring Framework has already made serious inroads as an integrated technology stack for building user-facing applications. Spring Framework Corporate TRaining the authors explore the idea of using Java in Big Data platforms.
    Specifically, Spring Framework provides various tasks are geared around preparing data for further analysis and visualization. Spring Training in Chennai

    ReplyDelete

Popular Posts