verbo tiempo que primera presente persona pasado mucho indicativo fuerces fuerce forzar forces force define correcto conjugacion java spring spring-boot

java - tiempo - Fuerce habilite DevTools con arranque de resorte cuando ejecute Jar



que es correcto fuerces o forces (1)

La solución es incompleta, por lo que decide si es bueno para usted. La solución final es la última parte de esta publicación

Es difícil lanzar la solución, primero necesito explicar cómo llegué allí. En primer lugar, porque livereload no está habilitado cuando se inicia fuera del IDE:

Comprenda lo que está pasando

(1) La configuración de LocalDevToolsAutoConfiguration es condicional en @ConditionalOnInitializedRestarter/OnInitializedRestarterCondition :

@Configuration @ConditionalOnInitializedRestarter @EnableConfigurationProperties(DevToolsProperties.class) public class LocalDevToolsAutoConfiguration { ...

(2) OnInitializedRestarterCondition recupera una instancia de reiniciador y comprueba si es nula; de lo contrario, restarter.getInitialUrls() devuelve null. En mi caso, restarter.getInitialUrls() devolvía nulo.

class OnInitializedRestarterCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { Restarter restarter = getRestarter(); if (restarter == null) { return ConditionOutcome.noMatch("Restarter unavailable"); } if (restarter.getInitialUrls() == null) { return ConditionOutcome.noMatch("Restarter initialized without URLs"); } return ConditionOutcome.match("Restarter available and initialized"); }

(3) initialUrls se inicializa en Restarter.class través de DefaultRestartInitializer.getInitialUrls(..)

class Restarter{ this.initialUrls = initializer.getInitialUrls(thread); } class DefaultRestartInitializer{ @Override public URL[] getInitialUrls(Thread thread) { if (!isMain(thread)) { return null; } for (StackTraceElement element : thread.getStackTrace()) { if (isSkippedStackElement(element)) { return null; } } return getUrls(thread); } protected boolean isMain(Thread thread) { return thread.getName().equals("main") && thread.getContextClassLoader() .getClass().getName().contains("AppClassLoader"); } }

thread.getContextClassLoader () .getClass (). getName (). contains ("AppClassLoader")

solo es cierto cuando se ejecuta desde Eclipse (posiblemente cualquier IDE? + springboot-maven-plugin?). Recordar:

  • isMain () devuelve falso;

  • el initialUrls no se inicializa;

  • el LocalConvToolsAutoConfiguration condicional no está configurado;

  • sin carga en vivo

UNA SOLUCIÓN:

Asegúrese de que el nombre del cargador de clases sea "AppClassLoader" creando su propio cargador de clases AppClassLoader. En la primera línea de la base de su bota de resorte, reemplace el cargador de clase con el suyo:

URLClassLoader originalClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(new CustomAppClassLoader(originalClassLoader));

Nuestra implementación personalizada del cargador de clases simplemente delega en la original:

public class CustomAppClassLoader extends URLClassLoader{ private URLClassLoader contextClassLoader; public CustomAppClassLoader(URLClassLoader contextClassLoader) { super(contextClassLoader.getURLs(), contextClassLoader.getParent()); this.contextClassLoader = contextClassLoader; } public int hashCode() { return contextClassLoader.hashCode(); } public boolean equals(Object obj) { return contextClassLoader.equals(obj); } public InputStream getResourceAsStream(String name) { return contextClassLoader.getResourceAsStream(name); } public String toString() { return contextClassLoader.toString(); } public void close() throws IOException { contextClassLoader.close(); } public URL[] getURLs() { return contextClassLoader.getURLs(); } public Class<?> loadClass(String name) throws ClassNotFoundException { return contextClassLoader.loadClass(name); } public URL findResource(String name) { return contextClassLoader.findResource(name); } public Enumeration<URL> findResources(String name) throws IOException { return contextClassLoader.findResources(name); } public URL getResource(String name) { return contextClassLoader.getResource(name); } public Enumeration<URL> getResources(String name) throws IOException { return contextClassLoader.getResources(name); } public void setDefaultAssertionStatus(boolean enabled) { contextClassLoader.setDefaultAssertionStatus(enabled); } public void setPackageAssertionStatus(String packageName, boolean enabled) { contextClassLoader.setPackageAssertionStatus(packageName, enabled); } public void setClassAssertionStatus(String className, boolean enabled) { contextClassLoader.setClassAssertionStatus(className, enabled); } public void clearAssertionStatus() { contextClassLoader.clearAssertionStatus(); }

}

Configuré CustomAppClassLoader tanto como pude (llamando a super con ''url'' y ''parent'' desde el cargador de clases original), pero igual sigo delegando todos los métodos públicos en el cargador de clases original.

Esto funciona para mi. Ahora, la mejor pregunta es, ¿realmente quiero esto? :)

Una mejor opción

Creo que Spring Cloud''s RestartEndpoint es una mejor opción: Spring Cloud''s RestartEndpoint programáticamente la aplicación Spring Boot Sin embargo, RestartEndPoint no maneja la detección de cambios en la ruta de clase.

Estoy ejecutando mi aplicación de arranque de primavera en un contenedor Docker, tratando de utilizar LiveReload remoto .

La documentación DevTools de arranque de primavera indica que

Las herramientas de desarrollador se desactivan automáticamente cuando se ejecuta una aplicación completamente empaquetada. Si su aplicación se inicia utilizando java -jar o si ha comenzado a usar un cargador de clases especial, entonces se considera una "aplicación de producción".

¿Hay alguna forma de forzar la habilitación de DevTools?