Hot questions for Spring Boot Devtools

Top 10 Java Open Source / Spring / Spring Boot Devtools

Question:

I obtained an exception when generated a stub for a WS service by wsimport in /target/class/..... and run a spring boot application with devtools.

Caused by: java.lang.IllegalArgumentException: com....Service referenced from a method is not visible from class loader

I found that an issue with spring devtools class loader, RestartClassLoader, because of two different references to a Class (RestartClassLoader and AppClassLoader)

private static void ensureVisible(ClassLoader ld, Class<?> c) {
    Class<?> type = null;
    try {
        type = Class.forName(c.getName(), false, ld);
    } catch (ClassNotFoundException e) {
        if (type != c) {
            throw new IllegalArgumentException(c.getName() +
                    " referenced from a method is not visible from class loader");
        }
    }
}

I was trying to add a reference to a jar file in spring-devtools.properties to restart.include=/.....jar

Spring Boot 2.0.0.RELEASE Java 9


Answer:

Since they are generated classes you have to exclude them from Spring Devtools "restart" classloader.

  1. Create a /src/main/resources/META-INF/spring-devtools.properties file
  2. Add properties like restart.exclude.* to exclude classes from restart classloader (example, you can use restart.exclude.mygeneratedclasses=/*[generated]*.class to exclude all classes with generated word as part of package or class name)

  3. Done. Now you can use devtools and have no issues with WS generated classes.

Reference:

[1] https://github.com/spring-projects/spring-boot/issues/4529

[2] https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-customizing-classload

Question:

I built an application using Spring, JPA, MySQL and Web. I developed a static page in template folder normally and it works.

But, when I change something on static page, I can't reload it with changes. Then, I open the pom.xml and added

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

I restart the application, but, still not working when I make some changes on the static page.

Is there something more to do?

My 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.engsoftware</groupId>
    <artifactId>cobranca</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>Cobranca</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</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-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

Answer:

In your eclipse top menu your "Project" -> "Build Automatically" ON ?

Question:

Before I start, I'd like to say that I already tried the solution proposed in spring-boot-devtools reload of multi-module maven project changes, which didn't work for me.

Problem:

I have a multi-module Spring Boot project of this sort:

The module launcher has a Maven dependency on module GUI. I launch my Spring Boot application from the main method in launcher.

When I run the application and change any HTML file in GUI module, the spring-boot-devtools dependency doesn't do a live reload of these changes for my running application. Not even manual restart of launcher helps. I need to compile GUI manually and then run launcher again.

What I tried:

  1. I tried defining the spring-boot-devtools dependency first in parent pom.xml, then in GUI module only and then in both at the same time.
  2. I tried adding spring.devtools.restart.additional-paths=../gui in my application.properties file as suggested in spring-boot-devtools reload of multi-module maven project changes. This does indeed trigger the reload (according to the log), but those changes just don't propagate to the jar file of GUI dependency. Also, before I even made this project into multi-module, there was no need for reloading just because of HTML files (nothing is being compiled) and I could see the changes right away.

I use Netbeans GUI if that's of any help. I also tried running the project from command line, with no success. The Maven packaging on all modules is set to jar.


Answer:

The fact that this works when you configure absolute paths in devtools tells me that this is mainly a work directory issue.

So this means that:

  • configured paths should be relative to where you launch the CLI
  • you should configure the same location as a work directory in the run configuration of your IDE (whatever configuration your IDE is using to launch your application should have such an option)

In your case: everything should be relative to your launcher module; this should be as well your work directory in your IDE.

Question:

I using Springboot to create my app, so in Springboot Doc says if I use devtools the tomcat will restart everty change in my code, but I use the maven panel to run my app just double click in spring-boot:run plugins, but when I change any code my tomcat don`t restart.

how can I fix this? tks


Answer:

This a guide I used some time ago to make it work: https://www.mkyong.com/spring-boot/intellij-idea-spring-boot-template-reload-is-not-working/

Basically you have two do 2 things:

  1. Enable "Build project automatically" from Settings->Build, Execution, Deployment->Compiler
  2. Go to Registry(Ctrl+A, type "Registry") and enable compiler.automake.allow.when.app.running and ide.windowSystem.autoShowProcessPopup

Question:

I'm following this guide https://medium.com/@lhartikk/development-environment-in-spring-boot-with-docker-734ad6c50b34 to try and get auto restart, live reload and remote debugging working with my simple spring boot application in a local docker container. I'm getting an error when the auto restart is triggered:

Exception in thread "File Watcher" java.lang.IllegalStateException: Unexpected 404 response uploading class files

Dockerfile:

FROM openjdk
VOLUME /tmp
ADD target/learn-docker-0.0.1-SNAPSHOT.jar app.jar
RUN sh -c 'touch /app.jar'
ENTRYPOINT ["java","-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Run command:

docker build -t learn_docker .
docker run -p 8080:8080 -d learn_docker

Answer:

I finally found the solution! You have to put the application context on the arguments of the IDE RemoteSpringApplication configuration.

For example, my application root context was /virtue so I had to configure it like so: