Search

Dark theme | Light theme

September 16, 2015

Spring Sweets: Reload Classes Spring Boot With Spring Loaded And Gradle Continuous Build

When we develop a Spring Boot application we can hot reload newly compiled classes using Gradle. The bootRun task of the Spring Boot Gradle plugin has support for Spring Loaded. We must add a dependency to Spring Loaded as a dependency for the classpath configuration in the buildscript block. If we now use the bootRun task everything is ready to reload changed classes. Now we can use the continuous build feature of Gradle to listen for changes in our source files to recompile them. The recompiled classes are then reloaded in the running Spring Boot application started with bootRun. We start a second Gradle instance with the -t option for the classes task. This way when we change a source file it gets recompiled automatically and reloaded.

The following build script shows how we add Spring Loaded:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE"
        classpath 'org.springframework:springloaded:1.2.4.RELEASE'
    }
}

apply plugin: 'groovy'
apply plugin: 'spring-boot'

jar {
    baseName = 'sample'
    version =  '1.0'
}

repositories {
    jcenter()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile "org.springframework.boot:spring-boot-starter-web"
    compile 'org.codehaus.groovy:groovy-all:2.4.4'
}

Let's also create a very simple Spring Boot application:

package com.mrhaki.sample

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.ResponseBody

@EnableAutoConfiguration
@Controller
class SampleController {

    @RequestMapping(value = '/', method = RequestMethod.GET)
    @ResponseBody
    String sample() {
        'Sample controller'
    }

    static void main(String... args) {
        SpringApplication.run(SampleController, args)
    }

}

Now we can start a Gradle proces that will recompile class files if the source file changes:

$ gradle -t classes
Continuous build is an incubating feature.
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes

BUILD SUCCESSFUL

Total time: 2.847 secs

Waiting for changes to input files of tasks... (ctrl-d to exit)

In another terminal we start the bootRun task:

$ gradle bootRun
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:bootRun
objc[16206]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.2.5.RELEASE)

...
> Building 83% > :bootRun

Written with Gradle 2.7 and Spring Boot 1.2.5.