spring-boot icon indicating copy to clipboard operation
spring-boot copied to clipboard

Support DevTools remote update in reactive web applications

Open ashirman opened this issue 6 years ago • 6 comments

Hello,

I am creating spring-boot application (version 2.0.1.RELEASE) using kotlin (1.2.41), java 8 (Oracle's JDK 1.8.0.172) and webflux provided by boot:spring-boot-starter-webflux starter. The application entry point looks like following

@SpringBootApplication
class DemoApplication

fun main(args: Array<String>) {
    val springApplication = SpringApplication(DemoApplication::class.java)
    springApplication.webApplicationType = WebApplicationType.REACTIVE

    springApplication.run()
}

it works fine from webflux stack perspective but it does not allow to use any functionality from spring-boot-devtools and Remote Update in particular. I've detected that devtools-related beans such as DispatcherFilter, UrlHandlerMapper, HttpRestartServerHandler etc were registered successfully in the context but the only issue is that webcontext of embedded tomcat is not aware of them at all. So, even filter bean was registered in the context it is not a part of embedded tomcat servlet context and it does not receive any incoming requests.

Need to note that I am aware of completely different conception of webflux/reactive flow comparing to old-way servlets/filtes flow. But at the same time I see no reason not to have devtools available within REACTIVE web application type. Please correct me if I am wrong.

Here is an example how it was possible to run devtools using TomcatReactiveWebServerFactory (was inspired mostly by this approach https://stackoverflow.com/a/48790976)

@Configuration
public class RemoteDevToolConf {

    @Autowired
    DispatcherFilter remoteDevToolsDispatcherFilter;

    @Bean
    public WebServerFactoryCustomizer<TomcatReactiveWebServerFactory> customizer() {

        return factory -> factory.addContextCustomizers(
                context -> {
                    context.addFilterDef(remoteToolFilterDefinition());
                    context.addFilterMap(devToolFilterMapping());
                }
        );
    }

    @NotNull
    private FilterDef remoteToolFilterDefinition() {
        FilterDef filterDef = new FilterDef();
        filterDef.setFilterName("remoteDevToolsDispatcherFilter");
        filterDef.setFilter(remoteDevToolsDispatcherFilter);
        return filterDef;
    }

    @NotNull
    private FilterMap devToolFilterMapping() {
        FilterMap filterMap = new FilterMap();
        filterMap.setFilterName("remoteDevToolsDispatcherFilter");
        filterMap.addURLPattern("/*");
        return filterMap;
    }
}

Well, after such a workaround (mostly because it works fine with tomcat and won't work fine with netty where we can't customise servlet context in a such way AFAIK) remote restart works fine and a URI .~~spring-boot!~/restart is available for clients.

My questions are following:

  1. Any reasons why spring-boot-devtools doesn't work out of the box with REACTIVE application context? Having said that is it an issue or explicitly defined behaviour?
  2. Any drawbacks in usage of devtools filters in a provided manner (ignoring the fact that it works fine with tomcat only so it can be handled by @ConditionalOn from what I feel)?

ashirman avatar May 08 '18 06:05 ashirman