错误:使用 Spring、Jersey 和 ehCache 时“同一 VM 中已存在另一个未命名的 CacheManager”

Ben*_*Ben 5 java spring ehcache jersey

似乎有另一个进程正在加载缓存,但无法找到它(如果错误没有告诉我谎言)。它告诉我的唯一一件事是,我有另一个缓存从一个名为InputStreamConfigurationSource的类开始?

有人遇到过这个错误吗???

我在用

  • 春天3
  • 球衣1.6/1.7
  • ehCache 2.6

堆栈跟踪

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)
Run Code Online (Sandbox Code Playgroud)

弹簧配置

<?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>
Run Code Online (Sandbox Code Playgroud)

网页 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>
Run Code Online (Sandbox Code Playgroud)

缓存文件

<ehcache>
<cache name="FileStoreList" maxElementsInMemory="10000" eternal="false"
    overflowToDisk="false" timeToIdleSeconds="0" timeToLiveSeconds="0"
    diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />
</ehcache>
Run Code Online (Sandbox Code Playgroud)

文件服务类

public class FileStoreService {

private final CacheManager cacheFactory;

private final DataAccessFactory factory;

public FileStoreService(@InjectParam DataAccessFactory factory, @InjectParam CacheManager ehCacheManager) {
    this.factory = factory;
    cacheFactory = ehCacheManager;
}
...
Run Code Online (Sandbox Code Playgroud)

JSON 端点

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() {

....
Run Code Online (Sandbox Code Playgroud)

Ben*_*Ben 0

正如这个问题“ Jersey @InjectParam 创建一个新对象而不是从 Spring 获取” 一样,使用了错误的 servlet。因此有两个容器启动,一个通过“ ContextLoaderListener ”用于 Spring,另一个通过“ ServletContainer ”用于 Jersey。这意味着正在启动两个缓存实例。

使用的Servlet容器应该是

 <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
Run Code Online (Sandbox Code Playgroud)

这样 Jersey 就可以附加到 Spring 容器上