12
votes

I'm porting 5 years old Spring MVC application with JSPs to Spring Boot. Therefore, according to sample in http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-jsp-limitations I'm using "war" packaging.

Embedded tomcat starts. However logs are full of caching warnings like in the example below

2016-08-25 14:59:01.442  INFO 28884 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-08-25 14:59:01.456  INFO 28884 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-08-25 14:59:01.458  INFO 28884 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.4
2016-08-25 14:59:01.531  WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache   : Unable to add the resource at [/WEB-INF/lib/displaytag-1.2.jar] to the cache because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2016-08-25 14:59:01.531  WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache   : Unable to add the resource at [/WEB-INF/lib/decrex-maven-0.1.10-SNAPSHOT.jar] to the cache because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2016-08-25 14:59:01.531  WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache   : Unable to add the resource at [/WEB-INF/lib/spring-boot-actuator-1.4.0.RELEASE.jar] to the cache because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2016-08-25 14:59:01.531  WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache   : Unable to add the resource at [/WEB-INF/lib/validation-api-1.1.0.Final.jar] to the cache because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2016-08-25 14:59:01.532  WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache   : Unable to add the resource at [/WEB-INF/lib/lucene-backward-codecs-5.3.1.jar] to the cache because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2016-08-25 14:59:01.532  WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache   : Unable to add the resource at [/WEB-INF/lib/lucene-queries-5.3.1.jar] to the cache because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
.....
2016-08-25 14:59:05.121  WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache   : Unable to add the resource at [/WEB-INF/lib/jstl-1.2.jar] to the cache because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2016-08-25 14:59:05.139  WARN 28884 --- [ost-startStop-1] org.apache.catalina.webresources.Cache   : Unable to add the resource at [/WEB-INF/classes/commons-logging.properties] to the cache because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2016-08-25 14:59:05.139  INFO 28884 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-08-25 14:59:05.139  INFO 28884 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 7117 ms
.....
2016-08-25 15:02:03.960  INFO 28884 --- [ndardContext[]]] org.apache.catalina.webresources.Cache   : The background cache eviction process was unable to free [10] percent of the cache for Context [] - consider increasing the maximum size of the cache. After eviction approximately [9,251] KB of data remained in the cache.

I'd be happy to increase tomcat cache, but I'm failing to find a way to control it in Spring Boot. Please, advise!!!


I tried a suggestion from Andy Wilkinson below. Also tried to use it in EmbeddedServletContainerCustomizer
@Component
public class ServletContainerCustomizer implements EmbeddedServletContainerCustomizer {

    private static final Log log = LogFactory.getLog(ServletContainerCustomizer.class);

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        if (TomcatEmbeddedServletContainerFactory.class.isAssignableFrom(container.getClass())) {

            int cacheSize = 256 * 1024;
            log.info("Customizing tomcat factory. New cache size (KB) is " + cacheSize);

            TomcatEmbeddedServletContainerFactory tomcatFactory = (TomcatEmbeddedServletContainerFactory) container;
            tomcatFactory.addContextCustomizers((context) -> {
                StandardRoot standardRoot = new StandardRoot(context);
                standardRoot.setCacheMaxSize(cacheSize);
            });

        }
    }

}

Message about changing the cache size is in the logs, but the code above has no influence on the warnings

3
There is a some info about this error: stackoverflow.com/questions/26893297/… As far I understand to increase the cache size you have to define EmbeddedServletContainerCustomizer - Slava Semushin
Thank you for the idea. I can get access to an instance of TomcatEmbeddedServletContainerFactory. However there are no methods, which can help to control caching - Viktor

3 Answers

13
votes

I've been having the same problem for a while, but Andy Wilkinson's hint set me on the right track. What worked for me was to set the cache as Andy did, but then also explicitly set the resources in context.

@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory() {
        @Override
        protected void postProcessContext(Context context) {
            final int cacheSize = 40 * 1024;
            StandardRoot standardRoot = new StandardRoot(context);
            standardRoot.setCacheMaxSize(cacheSize);
            context.setResources(standardRoot); // This is what made it work in my case.

            logger.info(String.format("New cache size (KB): %d", context.getResources().getCacheMaxSize()));
        }
    };
    return tomcatFactory;
}

Hope this helps!

4
votes

You can configure the cache size using a context customizer to configure the context with a customized StandardRoot:

Java 7:

@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
    TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();
    tomcatFactory.addContextCustomizers(new TomcatContextCustomizer() {

        @Override
        public void customize(Context context) {
            StandardRoot standardRoot = new StandardRoot(context);
            standardRoot.setCacheMaxSize(40 * 1024);
        }

    });
    return tomcatFactory;
}

Java 8:

@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
    TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();
    tomcatFactory.addContextCustomizers((context) -> {
        StandardRoot standardRoot = new StandardRoot(context);
        standardRoot.setCacheMaxSize(40 * 1024);
    });
    return tomcatFactory;
}
1
votes

Referring to there answer here, I created src/main/webapp/META-INF/context.xml and added the following.

<?xml version="1.0" encoding="UTF-8"?>
<Context>
  <Resources cachingAllowed="true" cacheMaxSize="204800" />
</Context>