diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java index b113708ace..c33748f8b7 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java @@ -105,7 +105,7 @@ public class LocalDevToolsAutoConfiguration { public void onClassPathChanged(ClassPathChangedEvent event) { if (event.isRestartRequired()) { Restarter.getInstance().restart( - new FileWatchingFailureHandler(getFileSystemWatcherFactory())); + new FileWatchingFailureHandler(fileSystemWatcherFactory())); } } @@ -114,7 +114,7 @@ public class LocalDevToolsAutoConfiguration { public ClassPathFileSystemWatcher classPathFileSystemWatcher() { URL[] urls = Restarter.getInstance().getInitialUrls(); ClassPathFileSystemWatcher watcher = new ClassPathFileSystemWatcher( - getFileSystemWatcherFactory(), classPathRestartStrategy(), urls); + fileSystemWatcherFactory(), classPathRestartStrategy(), urls); watcher.setStopWatcherOnRestart(true); return watcher; } @@ -127,7 +127,7 @@ public class LocalDevToolsAutoConfiguration { } @Bean - public FileSystemWatcherFactory getFileSystemWatcherFactory() { + public FileSystemWatcherFactory fileSystemWatcherFactory() { return new FileSystemWatcherFactory() { @Override diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/ClassPathFileChangeListener.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/ClassPathFileChangeListener.java index 8f07e2283c..47c2ecff39 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/ClassPathFileChangeListener.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/classpath/ClassPathFileChangeListener.java @@ -22,6 +22,7 @@ import org.springframework.boot.devtools.filewatch.ChangedFile; import org.springframework.boot.devtools.filewatch.ChangedFiles; import org.springframework.boot.devtools.filewatch.FileChangeListener; import org.springframework.boot.devtools.filewatch.FileSystemWatcher; +import org.springframework.boot.devtools.restart.AgentReloader; import org.springframework.context.ApplicationEventPublisher; import org.springframework.util.Assert; @@ -71,6 +72,9 @@ class ClassPathFileChangeListener implements FileChangeListener { } private boolean isRestartRequired(Set changeSet) { + if (AgentReloader.isActive()) { + return false; + } for (ChangedFiles changedFiles : changeSet) { for (ChangedFile changedFile : changedFiles) { if (this.restartStrategy.isRestartRequired(changedFile)) { diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/AgentReloader.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/AgentReloader.java new file mode 100644 index 0000000000..b4f348053b --- /dev/null +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/AgentReloader.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.devtools.restart; + +import org.springframework.util.ClassUtils; + +/** + * Utility to determine if an Java agent based reloader (e.g. JRebel) is being used. + * + * @author Phillip Webb + * @since 1.3.0 + */ +public abstract class AgentReloader { + + private AgentReloader() { + } + + /** + * Determine if any agent reloader is active. + * @return true if agent reloading is active + */ + public static boolean isActive() { + return isJRebelActive(); + } + + /** + * Determine if JRebel is active. + * @return true if JRebel is active + */ + public static boolean isJRebelActive() { + return ClassUtils.isPresent("org.zeroturnaround.javarebel.ReloaderFactory", null); + } + +} diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java index e1c5fda293..4ed4ba58c5 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java @@ -53,7 +53,10 @@ public class RestartApplicationListener implements ApplicationListener> for details. +NOTE: If you use JRebel automatic restarts will be disabled in favor of dynamic class +reloading. Other devtools features (such as LiveReload and property overrides) can still +be used. + .Restart vs Reload **** The restart technology provided by Spring Boot works by using two classloaders.