Browse Source

Deprecate LiveReload support for removal

Closes gh-48971
pull/49339/head
Brian Clozel 3 weeks ago
parent
commit
8018829ff5
  1. 10
      documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/using/devtools.adoc
  2. 3
      module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsProperties.java
  3. 12
      module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java
  4. 3
      module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/OptionalLiveReloadServer.java
  5. 1
      module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/livereload/Connection.java
  6. 2
      module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/livereload/LiveReloadServer.java
  7. 1
      module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/DelayedLiveReloadTrigger.java
  8. 17
      module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java
  9. 1
      module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfigurationTests.java
  10. 1
      module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/OptionalLiveReloadServerTests.java
  11. 1
      module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/livereload/LiveReloadServerTests.java
  12. 1
      module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/DelayedLiveReloadTriggerTests.java
  13. 3
      module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java

10
documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/using/devtools.adoc

@ -108,10 +108,8 @@ The way in which you cause the classpath to be updated depends on the tool that @@ -108,10 +108,8 @@ The way in which you cause the classpath to be updated depends on the tool that
NOTE: If you are restarting with Maven or Gradle using the build plugin you must leave the `forking` set to `enabled`.
If you disable forking, the isolated application classloader used by devtools will not be created and restarts will not operate properly.
TIP: Automatic restart works very well when used with LiveReload.
See the xref:using/devtools.adoc#using.devtools.livereload[] section for details.
If you use JRebel, automatic restarts are disabled in favor of dynamic class reloading.
Other devtools features (such as LiveReload and property overrides) can still be used.
TIP: If you use JRebel, automatic restarts are disabled in favor of dynamic class reloading.
Other devtools features (such as property overrides) can still be used.
NOTE: DevTools relies on the application context's shutdown hook to close it during a restart.
It does not work correctly if you have disabled the shutdown hook (`SpringApplication.setRegisterShutdownHook(false)`).
@ -287,11 +285,13 @@ If you find such a problem, you need to request a fix with the original authors. @@ -287,11 +285,13 @@ If you find such a problem, you need to request a fix with the original authors.
[[using.devtools.livereload]]
== LiveReload
WARNING: Given its decrease in popularity and support, the LiveReload feature is deprecated as of Spring Boot 4.1.0 with no replacement.
The `spring-boot-devtools` module includes an embedded LiveReload server that can be used to trigger a browser refresh when a resource is changed.
LiveReload browser extensions are freely available for Chrome, Firefox and Safari.
You can find these extensions by searching 'LiveReload' in the marketplace or store of your chosen browser.
If you want to start the LiveReload server when your application runs, you can set the configprop:spring.devtools.livereload.enabled[] property to `true`.
If you want to start the LiveReload server when your application runs, you can set the `spring.devtools.livereload.enabled` property to `true`.
NOTE: You can only run one LiveReload server at a time.
Before starting your application, ensure that no other LiveReload servers are running.

3
module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsProperties.java

@ -24,6 +24,7 @@ import java.util.List; @@ -24,6 +24,7 @@ import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.util.StringUtils;
@ -200,6 +201,7 @@ public class DevToolsProperties { @@ -200,6 +201,7 @@ public class DevToolsProperties {
*/
private int port = 35729;
@DeprecatedConfigurationProperty(reason = "Deprecated with no replacement", since = "4.1.0")
public boolean isEnabled() {
return this.enabled;
}
@ -208,6 +210,7 @@ public class DevToolsProperties { @@ -208,6 +210,7 @@ public class DevToolsProperties {
this.enabled = enabled;
}
@DeprecatedConfigurationProperty(reason = "Deprecated with no replacement", since = "4.1.0")
public int getPort() {
return this.port;
}

12
module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java

@ -37,7 +37,6 @@ import org.springframework.boot.devtools.classpath.PatternClassPathRestartStrate @@ -37,7 +37,6 @@ import org.springframework.boot.devtools.classpath.PatternClassPathRestartStrate
import org.springframework.boot.devtools.filewatch.FileSystemWatcher;
import org.springframework.boot.devtools.filewatch.FileSystemWatcherFactory;
import org.springframework.boot.devtools.filewatch.SnapshotStateRepository;
import org.springframework.boot.devtools.livereload.LiveReloadServer;
import org.springframework.boot.devtools.restart.ConditionalOnInitializedRestarter;
import org.springframework.boot.devtools.restart.RestartScope;
import org.springframework.boot.devtools.restart.Restarter;
@ -71,18 +70,20 @@ public final class LocalDevToolsAutoConfiguration { @@ -71,18 +70,20 @@ public final class LocalDevToolsAutoConfiguration {
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnBooleanProperty(name = "spring.devtools.livereload.enabled")
@SuppressWarnings("removal")
static class LiveReloadConfiguration {
@Bean
@RestartScope
@ConditionalOnMissingBean
LiveReloadServer liveReloadServer(DevToolsProperties properties) {
return new LiveReloadServer(properties.getLivereload().getPort(),
Restarter.getInstance().getThreadFactory());
org.springframework.boot.devtools.livereload.LiveReloadServer liveReloadServer(DevToolsProperties properties) {
return new org.springframework.boot.devtools.livereload.LiveReloadServer(
properties.getLivereload().getPort(), Restarter.getInstance().getThreadFactory());
}
@Bean
OptionalLiveReloadServer optionalLiveReloadServer(LiveReloadServer liveReloadServer) {
OptionalLiveReloadServer optionalLiveReloadServer(
org.springframework.boot.devtools.livereload.LiveReloadServer liveReloadServer) {
return new OptionalLiveReloadServer(liveReloadServer);
}
@ -160,6 +161,7 @@ public final class LocalDevToolsAutoConfiguration { @@ -160,6 +161,7 @@ public final class LocalDevToolsAutoConfiguration {
}
@SuppressWarnings("removal")
static class LiveReloadServerEventListener implements GenericApplicationListener {
private final OptionalLiveReloadServer liveReloadServer;

3
module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/OptionalLiveReloadServer.java

@ -30,7 +30,10 @@ import org.springframework.core.log.LogMessage; @@ -30,7 +30,10 @@ import org.springframework.core.log.LogMessage;
*
* @author Phillip Webb
* @since 1.3.0
* @deprecated since 4.1.0 for removal in 4.3.0 with no replacement.
*/
@Deprecated(since = "4.1.0", forRemoval = true)
@SuppressWarnings("removal")
public class OptionalLiveReloadServer implements InitializingBean {
private static final Log logger = LogFactory.getLog(OptionalLiveReloadServer.class);

1
module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/livereload/Connection.java

@ -40,6 +40,7 @@ import org.springframework.util.Assert; @@ -40,6 +40,7 @@ import org.springframework.util.Assert;
* @author Phillip Webb
* @author Francis Lavoie
*/
@SuppressWarnings("removal")
class Connection {
private static final Log logger = LogFactory.getLog(Connection.class);

2
module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/livereload/LiveReloadServer.java

@ -42,7 +42,9 @@ import org.springframework.util.Assert; @@ -42,7 +42,9 @@ import org.springframework.util.Assert;
*
* @author Phillip Webb
* @since 1.3.0
* @deprecated since 4.1.0 for removal in 4.3.0 with no replacement.
*/
@Deprecated(since = "4.1.0", forRemoval = true)
public class LiveReloadServer {
/**

1
module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/DelayedLiveReloadTrigger.java

@ -37,6 +37,7 @@ import org.springframework.util.Assert; @@ -37,6 +37,7 @@ import org.springframework.util.Assert;
*
* @author Phillip Webb
*/
@SuppressWarnings("removal")
class DelayedLiveReloadTrigger implements Runnable {
private static final long SHUTDOWN_TIME = 1000;

17
module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java

@ -36,7 +36,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean @@ -36,7 +36,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.devtools.autoconfigure.DevToolsProperties;
import org.springframework.boot.devtools.autoconfigure.DevToolsProperties.Restart;
import org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer;
import org.springframework.boot.devtools.autoconfigure.RemoteDevToolsProperties;
import org.springframework.boot.devtools.autoconfigure.RemoteDevToolsProperties.Proxy;
import org.springframework.boot.devtools.autoconfigure.TriggerFileFilter;
@ -46,7 +45,6 @@ import org.springframework.boot.devtools.classpath.ClassPathRestartStrategy; @@ -46,7 +45,6 @@ import org.springframework.boot.devtools.classpath.ClassPathRestartStrategy;
import org.springframework.boot.devtools.classpath.PatternClassPathRestartStrategy;
import org.springframework.boot.devtools.filewatch.FileSystemWatcher;
import org.springframework.boot.devtools.filewatch.FileSystemWatcherFactory;
import org.springframework.boot.devtools.livereload.LiveReloadServer;
import org.springframework.boot.devtools.restart.DefaultRestartInitializer;
import org.springframework.boot.devtools.restart.RestartScope;
import org.springframework.boot.devtools.restart.Restarter;
@ -71,6 +69,7 @@ import org.springframework.util.StringUtils; @@ -71,6 +69,7 @@ import org.springframework.util.StringUtils;
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(DevToolsProperties.class)
@SuppressWarnings("removal")
public class RemoteClientConfiguration implements InitializingBean {
private static final Log logger = LogFactory.getLog(RemoteClientConfiguration.class);
@ -152,14 +151,14 @@ public class RemoteClientConfiguration implements InitializingBean { @@ -152,14 +151,14 @@ public class RemoteClientConfiguration implements InitializingBean {
@Bean
@RestartScope
@ConditionalOnMissingBean
LiveReloadServer liveReloadServer() {
return new LiveReloadServer(this.properties.getLivereload().getPort(),
Restarter.getInstance().getThreadFactory());
org.springframework.boot.devtools.livereload.LiveReloadServer liveReloadServer() {
return new org.springframework.boot.devtools.livereload.LiveReloadServer(
this.properties.getLivereload().getPort(), Restarter.getInstance().getThreadFactory());
}
@Bean
ApplicationListener<ClassPathChangedEvent> liveReloadTriggeringClassPathChangedEventListener(
OptionalLiveReloadServer optionalLiveReloadServer) {
org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer optionalLiveReloadServer) {
return (event) -> {
String url = this.remoteUrl + this.properties.getRemote().getContextPath();
this.executor.execute(
@ -168,8 +167,10 @@ public class RemoteClientConfiguration implements InitializingBean { @@ -168,8 +167,10 @@ public class RemoteClientConfiguration implements InitializingBean {
}
@Bean
OptionalLiveReloadServer optionalLiveReloadServer(ObjectProvider<LiveReloadServer> liveReloadServer) {
return new OptionalLiveReloadServer(liveReloadServer.getIfAvailable());
org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer optionalLiveReloadServer(
ObjectProvider<org.springframework.boot.devtools.livereload.LiveReloadServer> liveReloadServer) {
return new org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer(
liveReloadServer.getIfAvailable());
}
final ExecutorService getExecutor() {

1
module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfigurationTests.java

@ -73,6 +73,7 @@ import static org.mockito.Mockito.reset; @@ -73,6 +73,7 @@ import static org.mockito.Mockito.reset;
* @author Vladimir Tsanev
*/
@ExtendWith(MockRestarter.class)
@SuppressWarnings("removal")
class LocalDevToolsAutoConfigurationTests {
private @Nullable ConfigurableApplicationContext context;

1
module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/OptionalLiveReloadServerTests.java

@ -30,6 +30,7 @@ import static org.mockito.Mockito.never; @@ -30,6 +30,7 @@ import static org.mockito.Mockito.never;
*
* @author Phillip Webb
*/
@SuppressWarnings("removal")
class OptionalLiveReloadServerTests {
@Test

1
module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/livereload/LiveReloadServerTests.java

@ -83,6 +83,7 @@ import static org.hamcrest.Matchers.not; @@ -83,6 +83,7 @@ import static org.hamcrest.Matchers.not;
* @author Phillip Webb
* @author Andy Wilkinson
*/
@SuppressWarnings("removal")
class LiveReloadServerTests {
private static final String HANDSHAKE = "{command: 'hello', "

1
module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/DelayedLiveReloadTriggerTests.java

@ -44,6 +44,7 @@ import static org.mockito.Mockito.never; @@ -44,6 +44,7 @@ import static org.mockito.Mockito.never;
* @author Phillip Webb
*/
@ExtendWith(MockitoExtension.class)
@SuppressWarnings("removal")
class DelayedLiveReloadTriggerTests {
private static final String URL = "http://localhost:8080";

3
module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java

@ -104,6 +104,7 @@ class RemoteClientConfigurationTests { @@ -104,6 +104,7 @@ class RemoteClientConfigurationTests {
}
@Test
@SuppressWarnings("removal")
void liveReloadOnClassPathChanged() {
configure("spring.devtools.livereload.enabled:true");
Set<ChangedFiles> changeSet = new HashSet<>();
@ -115,6 +116,7 @@ class RemoteClientConfigurationTests { @@ -115,6 +116,7 @@ class RemoteClientConfigurationTests {
}
@Test
@SuppressWarnings("removal")
void liveReloadDisabledByDefault() {
configure();
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
@ -185,6 +187,7 @@ class RemoteClientConfigurationTests { @@ -185,6 +187,7 @@ class RemoteClientConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
@SuppressWarnings("removal")
static class ClientConfig {
@Bean

Loading…
Cancel
Save