package net.andreaskluth; import java.util.ArrayList; import java.util.List; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; @Configuration public class WebMvcConfiguration extends WebMvcConfigurationSupport { @Autowired private RequestMappingHandlerAdapter requestMappingHandlerAdapter; @Bean public HandlerMethodReturnValueHandler completableFutureReturnValueHandler() { return new CompletableFutureReturnValueHandler(); } @PostConstruct public void init() { final List<HandlerMethodReturnValueHandler> originalHandlers = new ArrayList<>( requestMappingHandlerAdapter.getReturnValueHandlers()); final int deferredPos = obtainValueHandlerPosition(originalHandlers, DeferredResultMethodReturnValueHandler.class); // Add our handler directly after the deferred handler. originalHandlers.add(deferredPos + 1, completableFutureReturnValueHandler()); requestMappingHandlerAdapter.setReturnValueHandlers(originalHandlers); } private int obtainValueHandlerPosition(final List<HandlerMethodReturnValueHandler> originalHandlers, Class<?> handlerClass) { for (int i = 0; i < originalHandlers.size(); i++) { final HandlerMethodReturnValueHandler valueHandler = originalHandlers.get(i); if (handlerClass.isAssignableFrom(valueHandler.getClass())) { return i; } } return -1; } }