Spring Boot + Spring-Loaded (IntelliJ, Gradle)
Asked Answered
P

5

40

I'd like to use hot swap with my Spring Boot project. Somehow I am not able to make it working by running it in my IDE (IntelliJ), despite of having this topic covered by documentation. I simply run the class with my main method with VM attributes:

-javaagent:/path/to/jar/springloaded.jar -noverify

My question is, how do I make it work? :-)

Further question is how to use spring loaded with Gradle and IntelliJ. I find it quite inconvenient to force the developer to download the JAR manually, place it somewhere and point to it with a JVM parameter. Is there any better way (should I configure my own task which does the job and run it from my IDE as a Gradle task)?

Pedigree answered 23/6, 2014 at 16:44 Comment(12)
You said you read the documentation. Maybe you didn't spot the fact that the plugin downloads and attaches the agent for you?Marlinmarline
What you mean? You mean the gradle dependency? I am not sure as in doc it says that the dependency should be placed to buildscript block, therefore it is a dependency for the build script not the app - I don't understand it honestly. Could you give me some example please?Pedigree
The example in the docs is correct. You add the loaded dependency to the buildscript (so it is available to plugins). If you start gradle with --info you will see the agent being attached. What is it that doesn't work?Marlinmarline
I see the agent there "Attaching agent ... springloaded-1.2.0.RELEASE.jar" but it doesn't work anyway. Even when I run it from command line using gradle "gradle run" or "gradle bootRun". In my IDE, I usually run just the main class as I find it most convenient (start-up speed). I would like to have the reloading there but even specifying the springloaded.jar dependency (see my original question) doesn't help. I maybe miss something in the documentation or I am completely lost :-(Pedigree
Having springloaded as a dependency has no impact. Using "gradle run" will also have no effect and will not attach the agent. When you say "it doesn't work" what do you mean exactly? The agent is attached, so it must be doing something.Marlinmarline
So then I don't understand what has the effect on the reloading (or the agent being loaded). By "it doesn't work", I meant that the reloading is not working. I have a simple rest controller with simple rest function which returns some text. When I run the app (i.e. "gradle bootRun --info" in command line), change the returned text I don't see any effect when calling the REST connector. I don't see also any kind of compilation output or whatever, like I can see in Grails when I change some class.Pedigree
I have tried also this project: github.com/berlin-ab/springbootblog/tree/blog/hot-reload with no effect. I use JDK 8, could this be a problem?Pedigree
Changing the source code is not enough on its own. You need to recompile and replace the class file. IntelliJ is a bit fussy about that, so you might have to a) make sure it compiles, b) make sure it puts .class files in the same place as gradle (or not use gradle).Marlinmarline
@Pedigree just FYI if you prefer running the main class anyway, you can do so quite fine: put a keyboard shortcut on Run -> Reload changed classes. This also migth be handy also with using SL.Amandine
@Amandine that's nice :)! But I think that then the spring-loaded won't work, since it's provided by Gradle (at least when you configure it the way gradle recomends...). If that's correct you would only be allowed to reload changes in a method body, right?Heulandite
Any ideas how to get this going in Netbeans with the Gradle plugin?Hypocrisy
Looks like the real netbeans issue is "compile on save" with the Gradle plugin...Hypocrisy
H
26

You need to configure the project as stated in the documentation:

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-reload-springloaded-gradle-and-intellij-idea

After that, you must configure your IDE to output the compiled classes in build/classes/main (with Idea plugin, you can configure the outputDir as specified in the above link, and then invoke gradle idea to have it done).

Then, if you launch the task (run / bootRun) or run the main class from the IDE's using the debug mode, hot code reloading should work when a class is compiled.

The gotcha here is that IntelliJ, unlike Eclipse, doesn't automatically compile a class when it is saved (even if you configure the compiler to "Build on save", it won't do it when is Running/Debugging). This is apparently a design decission made by IntelliJ - as stated here Intellij IDEA Java classes not auto compiling on save (CrazyCoder answer) .

It would be ideal if spring boot provided a configuration option to monitor your source code files and recompile them when they change - that is what Grails does. But I think such a think does not exist yet, and maybe is not even possible to combine that with gradle, which is the responsible of managing the classpath and that kind of things.

So there are two options as far as I can tell:

  • You remember to compile everything you edit (adding an easier Compile shortcut as suggested in the previous StackOverflow link might help).
  • You put some filesystem monitor (inotify-tools for Linux, launchd for Mac OS X are examples) that invokes gradle compileJava/compileGroovy when a change is detected in any source code file.

First is tedious, second is slow :) . Actually there's another option: you change your IDE :-D (or install the EclipseMode IntelliJ plugin).

Heulandite answered 24/6, 2014 at 13:28 Comment(4)
Thank you all for suggestions, I think I will go for the IDEA shortcut for "Run -> Reload changed classes" suggested by @Amandine as I run the app from my IDE by running the main method. I think that any gradle plugin which will watch source files and build them in case of change would be really nicePedigree
For how to configure a Save and Build shortcut in IntelliJ see this: #14636102Elutriate
The given link for howto-reload-springloaded-gradle-and-intellij-idea is broken.Dragonet
gradle -t classes on a separate terminal works fine as well.Janusfaced
S
25

If one wants to be able to run the application solely from IntelliJ (using Right Click -> Debug on the main method) and not involve Spring Boot's Gradle tasks at all, you simply need to do the following:

  1. Configure the run configuration in IntelliJ to use the SpringLoaded agent. This is easy to do and an example is shown in the following screenshot:

enter image description here

Notice how I have added a VM Option: -javaagent:/path/to/springloaded-${version}.jar -noverify (which you can download here)

  1. Debug using Right Click -> Debug like the following screenshot:

enter image description here

  1. Everytime you make a change and want to reload it, just compile the project. The default shortcut is Cntrl+F9, but you can also access it from the menu Build -> Make Project
Simple answered 30/9, 2014 at 10:44 Comment(0)
I
9

I managed to do this with IDEA in a Maven project, it should work with the Gradle version as well I guess, my procedure was the following.

  • Settings -> Compiler -> Make project automatically (only works while not running/debugging !)
  • Start the project with the sprint-boot-plugin outside of the IDE (a trick because of the above sentence).

The Maven plugins setup looks like the following:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>springloaded</artifactId>
                    <version>1.2.0.RELEASE</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

Now change some code and reload the page.

Isogamy answered 8/8, 2014 at 15:27 Comment(0)
H
7

I'm running SpringBoot and Gradle in IntelliJ Idea. Auto-reloading is working 100%

  • Static Content is autoreloading (instantly)
  • Thymeleaf is autoreloading (instantly)
  • Controllers / Java Files require me to hit the "build" button (takes a few seconds), but does not require a restart - it's just to compile the files, so Spring Loaded can pick them up.

Step 1: Get SpringLoaded going

buildscript {
    repositories {
        mavenCentral()
        jcenter()
    }

    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.1.RELEASE"
        classpath 'org.springframework:springloaded:1.2.1.RELEASE'
    }
}

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'idea'
apply plugin: 'spring-boot'

repositories {
    jcenter()
    mavenLocal()
    mavenCentral()
}

mainClassName = 'com.noxgroup.nitro.NitroApp'

idea {
    module {
        inheritOutputDirs = false
        outputDir = file("$buildDir/classes/main/")
    }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
}

jar {
    baseName = 'org.noxgroup-nitro'
    version =  '0.1.0'
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}

Step 2: Create an Application.properties

And add the following:

spring.thymeleaf.cache=false

Step 3: Run the bootRun task

(Not just the standard run task - this adds SpringLoaded functionality)

Step 4: Compile your Java

Make your Java files by hitting "Make Project" or pressing "Ctrl/Command + F9

Hypocrisy answered 2/3, 2015 at 13:20 Comment(1)
This led me down the right path but I had to use org.springframework:springloaded:1.2.4.RELEASE as my spring loaded version in particular - thanksRivard
S
6

In later versions of gradle you can start a command window and run

gradle -t classes

This will start a process that look for changes to source code and recompile them.

In another run.

gradle bootRun

Any changes to java or groovy src will automatically be recomplied. While not intellij specific, your good to go with intellij. You could even make do with you favorite text editor (e.g. submlime, atom ).

credits/link

Stallings answered 3/2, 2016 at 0:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.