I'm trying to enhance the Spring version of the apache-james by adding some ad-hoc actuator @RestController
s.
In order to do so, I was thinking to start an embedded Tomcat 9.x server as a sidecar so that the endpoints can be accessible.
Unfortunately, I get a IllegalStateException: No ServletContext set
exception.
The code I've so far is the following:
/**
* @author cdprete
* @since 09.06.21
*/
public class EmbeddedTomcat implements DisposableBean {
private final Tomcat tomcat;
public EmbeddedTomcat() throws LifecycleException {
String appBase = ".";
tomcat = new Tomcat();
tomcat.getConnector();
tomcat.getHost().setAppBase(appBase);
Context context = tomcat.addWebapp("", appBase);
// Don't scan MANIFESTs, otherwise lots of JARs will be reported as missing
((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
tomcat.start();
}
@Override
public void destroy() throws Exception {
tomcat.destroy();
}
}
/**
* @author cdprete
* @since 08.06.21
*/
@EnableWebMvc
@Configuration
@Import({HealthConfiguration.class, DiskSpaceConfiguration.class, PingConfiguration.class, TraceConfiguration.class})
public class ActuatorConfiguration implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ActuatorConfiguration.class);
ctx.setServletContext(servletContext);
servletContext.addListener(new ContextLoaderListener(ctx));
ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
and in the main spring.xml
file:
<beans ...>
...
<!-- Embedded Tomcat -->
<bean class="ch.ti8m.channelsuite.james.actuator.EmbeddedTomcat" />
<!-- Actuator configuration -->
<bean class="ch.ti8m.channelsuite.james.actuator.ActuatorConfiguration" />
</beans>
If I start Tomcat from the main
method (e.g., like in here), then the web application works as expected (at least the one in the linked example).
What am I missing?
Everything works as expected if the class implementing the WebApplicationInitializer
interface is declared before the one having the @EnableWebMvc
. In particular, it's not even necessary to add the latter to the context since it's already registered in the context initiated in the WebApplicationInitializer