Allow Devtools to be enabled irrespective of the launching ClassLoader

Closes gh-21424
pull/24147/head
Andy Wilkinson 4 years ago
parent 30bc0ad96a
commit 6df10842d2

@ -43,14 +43,38 @@ public class DefaultRestartInitializer implements RestartInitializer {
}
/**
* Returns if the thread is for a main invocation. By default checks the name of the
* thread and the context classloader.
* Returns if the thread is for a main invocation. By default {@link #isMain(Thread)
* checks the name of the thread} and {@link #isDevelopmentClassLoader(ClassLoader)
* the context classloader}.
* @param thread the thread to check
* @return {@code true} if the thread is a main invocation
* @see #isMainThread
* @see #isDevelopmentClassLoader(ClassLoader)
*/
protected boolean isMain(Thread thread) {
return thread.getName().equals("main")
&& thread.getContextClassLoader().getClass().getName().contains("AppClassLoader");
return isMainThread(thread) && isDevelopmentClassLoader(thread.getContextClassLoader());
}
/**
* Returns whether the given {@code thread} is considered to be the main thread.
* @param thread the thread to check
* @return {@code true} if it's the main thread, otherwise {@code false}
* @since 2.4.0
*/
protected boolean isMainThread(Thread thread) {
return thread.getName().equals("main");
}
/**
* Returns whether the given {@code classLoader} is one that is typically used during
* development.
* @param classLoader the ClassLoader to check
* @return {@code true} if it's a ClassLoader typically used during development,
* otherwise {@code false}
* @since 2.4.0
*/
protected boolean isDevelopmentClassLoader(ClassLoader classLoader) {
return classLoader.getClass().getName().contains("AppClassLoader");
}
/**

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -64,7 +64,24 @@ public class RestartApplicationListener implements ApplicationListener<Applicati
// It's too early to use the Spring environment but we should still allow
// users to disable restart using a System property.
String enabled = System.getProperty(ENABLED_PROPERTY);
if (enabled == null || Boolean.parseBoolean(enabled)) {
RestartInitializer restartInitializer = null;
if (enabled == null) {
restartInitializer = new DefaultRestartInitializer();
}
else if (Boolean.parseBoolean(enabled)) {
restartInitializer = new DefaultRestartInitializer() {
@Override
protected boolean isDevelopmentClassLoader(ClassLoader classLoader) {
return true;
}
};
logger.info(LogMessage.format(
"Restart enabled irrespective of application packaging due to System property '%s' being set to true",
ENABLED_PROPERTY));
}
if (restartInitializer != null) {
String[] args = event.getArgs();
DefaultRestartInitializer initializer = new DefaultRestartInitializer();
boolean restartOnInitialize = !AgentReloader.isActive();

@ -88,6 +88,14 @@ class RestartApplicationListenerTests {
assertThat(output).contains("Restart disabled due to System property");
}
@Test
void enableWithSystemProperty(CapturedOutput output) {
System.setProperty(ENABLED_PROPERTY, "true");
testInitialize(false);
assertThat(Restarter.getInstance()).hasFieldOrPropertyWithValue("enabled", true);
assertThat(output).contains("Restart enabled irrespective of application packaging due to System property");
}
private void testInitialize(boolean failed) {
Restarter.clearInstance();
RestartApplicationListener listener = new RestartApplicationListener();

@ -542,7 +542,10 @@ To include devtools support, add the module dependency to your build, as shown i
NOTE: Developer tools are automatically disabled when running a fully packaged application.
If your application is launched from `java -jar` or if it is started from a special classloader, then it is considered a "`production application`".
If that does not apply to you (i.e. if you run your application from a container), consider excluding devtools or set the `-Dspring.devtools.restart.enabled=false` system property.
You can control this behavior by using the `spring.devtools.restart.enabled` system property.
To enable devtools, irrespective of the classloader used to launch your application, set the `-Dspring.devtools.restart.enabled=true` system property.
This must not be done in a production environment where running devtools is a security risk.
To disable devtools, exclude the dependency or set the `-Dspring.devtools.restart.enabled=false` system property.
TIP: Flagging the dependency as optional in Maven or using the `developmentOnly` configuration in Gradle (as shown above) prevents devtools from being transitively applied to other modules that use your project.

Loading…
Cancel
Save