0

I am upgrading a Spring/Angular application from Tomcat 7.0.59 to 7.0.99. I am using an embedded Tomcat server and running the app from the command line ("tomcat7:run-war").

The problem is that default welcome files are being added to the context (from Tomcat.initWebappDefaults()). The Tomcat code is adding a defaultWebXmlListener in Tomcat.addWebapp, which adds a bunch of stuff, including "index.html", "index.htm", and "index.jsp". I want index.html and index.htm to be removed, but embedded Tomcat is forcing them in. My application's web.xml is being found, but the welcome files are being appended to the list, not replacing.

When I run tomcat 7.0.59 from the command line, it works fine and doesn't add the extra welcome files.

When I run tomcat 7.0.99 from inside IntelliJ using an external server, it works fine and doesn't add the extra welcome files.

1 Answers1

0

So two things: Tomcat 7.0.100 adds a (sort of) fix for this. According to Bug 62755, a setter for "setAddDefaultWebXmlToWebapp" was added to Tomcat.java to prevent the default config from being added. (Problem is, I don't know how to set this flag in my application code).

My actual solution was to do some reflective meddling in the context, during the onStartup of my SpringBootServletInitializer.

public void contextInitialized(ServletContextEvent event) {
    //Remove the default welcome files that embedded Tomcat 7.0.99 adds because they become auto-concatenated to requests without a file
    try {
        final ApplicationContext appCtx = (ApplicationContext) get(ApplicationContextFacade.class, servletContext);
        final Context tomcatCtx = (Context) get(ApplicationContext.class, appCtx);
        tomcatCtx.removeWelcomeFile("index.html");
        tomcatCtx.removeWelcomeFile("index.htm");
   } catch (final Exception e) {
        e.printStackTrace();
   }
}
...
private static Object get(final Class<?> clazz, final Object facade) throws Exception {
    final Field field = clazz.getDeclaredField("context");
    final boolean acc = field.isAccessible();
    field.setAccessible(true);
    try {
      return field.get(facade);
    } finally {
      field.setAccessible(acc);
    }
  }

This can also be done in a ServletContextListener.contextInitialized method.