Saturday, January 21, 2017

Embedded Tomcat without JSP support

I am developing a Java web application consisting of a HTML 5 single page application and REST services using embedded Tomcat as the Java application server. I am not using JSPs and I did not want to include those dependencies in my application. Stack Overflow points to Tomcat.initWebappDefaults as being required to initialize the DefaultServlet for static content but it also adds JSPServlet as well. According to the Tomcat documentation applications should extend org.apache.catalina.startup.Tomcat to setup the default web xml context but I had an issue with this plus I didn't want to do a bunch of rework to setup the application.
Additionally I had issues with setting a base application and auto deploying war files in a directory.
Below is my solution to remove the JSPServlet before startup.


Path tomcatBase = appHome.resolve("web");
Files.createDirectories(tomcatBase);
tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.setBaseDir(tomcatBase.toString());
tomcat.getHost().setAppBase(tomcatBase.resolve("apps").toString());
tomcat.getHost().setAutoDeploy(true);
tomcat.getHost().setDeployOnStartup(true);
tomcat.getHost().addLifecycleListener(new HostConfig());
tomcat.getHost().setConfigClass(NoJSPServletContextConfig.class.getName());
tomcat.start();

...

// until https://github.com/apache/tomcat/pull/40 is addressed cannot
  // subclass tomcat so remove JSP support directly.
 public static class NoJSPServletContextConfig extends ContextConfig {
  
  @Override
  public void lifecycleEvent(LifecycleEvent event) {
   if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) {
    Context ctx = (Context) event.getLifecycle();
    Tomcat.initWebappDefaults(ctx);
    Container jspServlet = ctx.findChild("jsp");
    if (jspServlet != null) {
     for (String pattern : ctx.findServletMappings()) {
      String servletName = ctx.findServletMapping(pattern);
      if ("jsp".equals(servletName)) {
       ctx.removeServletMapping(pattern);
      }
     }
     ctx.removeChild(jspServlet);
    }
   }
   super.lifecycleEvent(event);
  }
  
 }