Java – Error : “Another unnamed CacheManager already exists in the same VM” Using Spring, Jersey and ehCache

ehcachejavajerseyspring

There seems to be another process loading the cache, but not able to locate this (that's if the error isn't telling me lie). The only thing its telling me is that i have another cache started somewhere from a class called InputStreamConfigurationSource ???

Has anyone come across this error ???

I am using

  • Spring 3
  • Jersey 1.6/1.7
  • ehCache 2.6

StackTrace

SEVERE: Servlet.service() for servlet [SpringDispatcher] in context with path [/FileService] threw exception [com.sun.jersey.api.container.ContainerException: Unable to create resource class com.myapp.FileStoreAccessAction] with root cause
net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same  VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: InputStreamConfigurationSource [stream=java.io.BufferedInputStream@e782a8]
at net.sf.ehcache.CacheManager.assertNoCacheManagerExistsWithSameName(CacheManager.java:521)
at net.sf.ehcache.CacheManager.init(CacheManager.java:371)
at net.sf.ehcache.CacheManager.<init>(CacheManager.java:356)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.sun.jersey.server.spi.component.ResourceComponentConstructor._construct(ResourceComponentConstructor.java:191)
at com.sun.jersey.server.spi.component.ResourceComponentConstructor.construct(ResourceComponentConstructor.java:179)
at com.sun.jersey.server.impl.resource.PerRequestFactory$PerRequest._getInstance(PerRequestFactory.java:182)
at com.sun.jersey.server.impl.resource.PerRequestFactory$AbstractPerRequest.getInstance(PerRequestFactory.java:144)
at com.sun.jersey.server.impl.application.WebApplicationImpl$19$1.getValue(WebApplicationImpl.java:1032)
at com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable$1.getValue(AbstractHttpContextInjectable.java:104)
at com.sun.jersey.server.spi.component.ResourceComponentConstructor._construct(ResourceComponentConstructor.java:196)
at com.sun.jersey.server.spi.component.ResourceComponentConstructor.construct(ResourceComponentConstructor.java:179)
at com.sun.jersey.server.impl.resource.PerRequestFactory$PerRequest._getInstance(PerRequestFactory.java:182)
at com.sun.jersey.server.impl.resource.PerRequestFactory$AbstractPerRequest.getInstance(PerRequestFactory.java:144)
at com.sun.jersey.server.impl.application.WebApplicationImpl$19$1.getValue(WebApplicationImpl.java:1032)
at com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable$1.getValue(AbstractHttpContextInjectable.java:104)
at com.sun.jersey.server.spi.component.ResourceComponentInjector.inject(ResourceComponentInjector.java:222)
at com.sun.jersey.server.spi.component.ResourceComponentConstructor.construct(ResourceComponentConstructor.java:180)
at com.sun.jersey.server.impl.resource.PerRequestFactory$PerRequest._getInstance(PerRequestFactory.java:182)
at com.sun.jersey.server.impl.resource.PerRequestFactory$AbstractPerRequest.getInstance(PerRequestFactory.java:144)
at com.sun.jersey.server.impl.application.WebApplicationContext.getResource(WebApplicationContext.java:238)
at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:83)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1480)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1411)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1360)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1350)
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

Spring Config

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">


<!-- Enable annotation configuration -->
<context:annotation-config/>

<context:component-scan base-package="com.myapp" />

<!-- Jackson JSON ObjectMapper -->
<bean id="objectMapper" class="org.codehaus.jackson.map.ObjectMapper" />

<!-- Cache Manager -->
<bean id="ehCacheManager"
    class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" scope="singleton">
    <property name="configLocation" value="classpath:cacheConfig.xml" />
    <property name="shared" value="true"/>
</bean>

<!-- Data Access -->
<bean id="dataAccessFactory" class="com.myapp.DataAccessFactory" />

<!-- Application Stuff -->
<bean id="fileStoreService" class="com.myapp.FileStoreService" scope="singleton">
    <constructor-arg ref="dataAccessFactory"/>
    <constructor-arg ref="ehCacheManager" />
</bean>

</beans>

Web xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">

<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:appContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
    <servlet-name>SpringDispatcher</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>SpringDispatcher</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Cache file

<ehcache>
<cache name="FileStoreList" maxElementsInMemory="10000" eternal="false"
    overflowToDisk="false" timeToIdleSeconds="0" timeToLiveSeconds="0"
    diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />
</ehcache>

File Service Class

public class FileStoreService {

private final CacheManager cacheFactory;

private final DataAccessFactory factory;

public FileStoreService(@InjectParam DataAccessFactory factory, @InjectParam CacheManager ehCacheManager) {
    this.factory = factory;
    cacheFactory = ehCacheManager;
}
...

JSON End Point

public class FileStoreAccessAction {

/**
 * JSON Object Mapper - pasted in via Spring
 */
@InjectParam
private ObjectMapper mapper;

@InjectParam()
private FileStoreService service;

@GET
@Produces(MediaType.APPLICATION_JSON)
public Response list() {

....

Best Answer

As with this question " Jersey @InjectParam creating a new Object instead of taking from Spring " The wrong servlet was being used. So there were two container starting, one for Spring via the "ContextLoaderListener" and one for Jersey via "ServletContainer". This meant two instance of the cache were being started.

the Servlet container used should be

 <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>

so Jersey can attach to the Spring Container