Permalink
Browse files

ISPN-2936 Move REST Server cache manager to ServletContext

Moved cache manager to ServletContext, added TwoServerTest.
  • Loading branch information...
1 parent f37c419 commit 77eec935539af6ae1ced1c835075074aa8e93e38 @mlinhard mlinhard committed with danberindei Feb 4, 2013
@@ -38,6 +38,7 @@ import org.infinispan.commons.hash.MurmurHash3
import org.infinispan.util.concurrent.ConcurrentMapFactory
import javax.ws.rs._
import javax.servlet.http.HttpServletResponse
+import javax.servlet.ServletContext
/**
* Integration server linking REST requests with Infinispan calls.
@@ -47,18 +48,19 @@ import javax.servlet.http.HttpServletResponse
* @since 4.0
*/
@Path("/rest")
-class Server(@Context request: Request, @HeaderParam("performAsync") useAsync: Boolean) {
+class Server(@Context request: Request, @Context servletContext: ServletContext, @HeaderParam("performAsync") useAsync: Boolean) {
/**For dealing with binary entries in the cache */
lazy val variantList = Variant.VariantListBuilder.newInstance.mediaTypes(MediaType.APPLICATION_XML_TYPE, MediaType.APPLICATION_JSON_TYPE).build
lazy val jsonMapper = new ObjectMapper
lazy val xstream = new XStream
+ val manager = servletContext.getAttribute(ServerBootstrap.MANAGER).asInstanceOf[ManagerInstance]
@GET
@Path("/{cacheName}/{cacheKey}")
def getEntry(@PathParam("cacheName") cacheName: String, @PathParam("cacheKey") key: String): Response = {
protectCacheNotFound(request, useAsync) { (request, useAsync) =>
- ManagerInstance.getEntry(cacheName, key) match {
+ manager.getEntry(cacheName, key) match {
case b: MIMECacheEntry => {
val lastMod = new Date(b.lastModified)
request.evaluatePreconditions(lastMod, calcETAG(b)) match {
@@ -96,7 +98,7 @@ class Server(@Context request: Request, @HeaderParam("performAsync") useAsync: B
@Path("/{cacheName}/{cacheKey}")
def headEntry(@PathParam("cacheName") cacheName: String, @PathParam("cacheKey") key: String): Response = {
protectCacheNotFound(request, useAsync) { (request, useAsync) =>
- ManagerInstance.getEntry(cacheName, key) match {
+ manager.getEntry(cacheName, key) match {
case b: MIMECacheEntry => {
val lastMod = new Date(b.lastModified)
request.evaluatePreconditions(lastMod, calcETAG(b)) match {
@@ -118,11 +120,11 @@ class Server(@Context request: Request, @HeaderParam("performAsync") useAsync: B
@DefaultValue("-1") @HeaderParam("timeToLiveSeconds") ttl: Long,
@DefaultValue("-1") @HeaderParam("maxIdleTimeSeconds") idleTime: Long): Response = {
protectCacheNotFound(request, useAsync) { (request, useAsync) =>
- val cache = ManagerInstance.getCache(cacheName)
+ val cache = manager.getCache(cacheName)
if (request.getMethod == "POST" && cache.containsKey(key)) {
Response.status(Status.CONFLICT).build()
} else {
- ManagerInstance.getEntry(cacheName, key) match {
+ manager.getEntry(cacheName, key) match {
case mime: MIMECacheEntry => {
// The item already exists in the cache, evaluate preconditions based on its attributes and the headers
val lastMod = new Date(mime.lastModified)
@@ -195,7 +197,7 @@ class Server(@Context request: Request, @HeaderParam("performAsync") useAsync: B
@DELETE
@Path("/{cacheName}/{cacheKey}")
def removeEntry(@PathParam("cacheName") cacheName: String, @PathParam("cacheKey") key: String): Response = {
- ManagerInstance.getEntry(cacheName, key) match {
+ manager.getEntry(cacheName, key) match {
case b: MIMECacheEntry => {
// The item exists in the cache, evaluate preconditions based on its attributes and the headers
val lastMod = new Date(b.lastModified)
@@ -205,19 +207,19 @@ class Server(@Context request: Request, @HeaderParam("performAsync") useAsync: B
// Preconditions passed
case null => {
if (useAsync) {
- ManagerInstance.getCache(cacheName).removeAsync(key)
+ manager.getCache(cacheName).removeAsync(key)
} else {
- ManagerInstance.getCache(cacheName).remove(key)
+ manager.getCache(cacheName).remove(key)
}
Response.ok.build
}
}
}
case obj: Any => {
if (useAsync) {
- ManagerInstance.getCache(cacheName).removeAsync(key)
+ manager.getCache(cacheName).removeAsync(key)
} else {
- ManagerInstance.getCache(cacheName).remove(key)
+ manager.getCache(cacheName).remove(key)
}
Response.ok.build
}
@@ -233,7 +235,7 @@ class Server(@Context request: Request, @HeaderParam("performAsync") useAsync: B
@DefaultValue("") @HeaderParam("If-Modified-Since") ifModifiedSince: String,
@DefaultValue("") @HeaderParam("If-Unmodified-Since") ifUnmodifiedSince: String): Response = {
if (ifMatch.isEmpty && ifNoneMatch.isEmpty && ifModifiedSince.isEmpty && ifUnmodifiedSince.isEmpty) {
- ManagerInstance.getCache(cacheName).clear()
+ manager.getCache(cacheName).clear()
Response.ok.build
} else {
preconditionNotImplementedResponse()
@@ -266,8 +268,7 @@ class Server(@Context request: Request, @HeaderParam("performAsync") useAsync: B
/**
* Just wrap a single instance of the Infinispan cache manager.
*/
-object ManagerInstance {
- var instance: EmbeddedCacheManager = null
+class ManagerInstance(instance: EmbeddedCacheManager) {
private[rest] val knownCaches : java.util.Map[String, Cache[String, Any]] =
ConcurrentMapFactory.makeConcurrentMap(4, 0.9f, 16)
@@ -292,6 +293,8 @@ object ManagerInstance {
def getEntry(cacheName: String, key: String): Any = getCache(cacheName).get(key)
+ def getInstance = instance
+
}
class CacheNotFoundException(msg: String) extends CacheException(msg)
@@ -0,0 +1,137 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+package org.infinispan.rest;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.rest.logging.JavaLog;
+import org.infinispan.util.logging.LogFactory;
+
+/**
+ * Initializes cache manager for the REST server and sets it into the servlet context.
+ *
+ * @author Michal Linhard (mlinhard@redhat.com)
+ * @since 5.2
+ */
+public class ServerBootstrap implements ServletContextListener {
+
+ private final static JavaLog log = LogFactory.getLog(ServerBootstrap.class, JavaLog.class);
+
+ public final static String MANAGER = "org.infinispan.rest.ServerBootstrap.MANAGER";
+
+ private void setManager(ServletContextEvent sce, EmbeddedCacheManager cacheManager) {
+ setToServletContext(sce.getServletContext(), cacheManager);
+ }
+
+ private EmbeddedCacheManager getManager(ServletContextEvent sce) {
+ ManagerInstance managerInstance = (ManagerInstance) sce.getServletContext().getAttribute(MANAGER);
+ return managerInstance == null ? null : managerInstance.getInstance();
+ }
+
+ public static void setToServletContext(ServletContext servletContext, EmbeddedCacheManager cacheManager) {
+ servletContext.setAttribute(MANAGER, new ManagerInstance(cacheManager));
+ }
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ EmbeddedCacheManager cm = getManager(sce);
+
+ if (cm == null) {
+ cm = getMcInjectedCacheManager(sce.getServletContext());
+ setManager(sce, cm);
+ }
+
+ // If cache manager is still null, create one for REST server's own usage
+ if (cm == null) {
+ String cfgFile = sce.getServletContext().getInitParameter("infinispan.config");
+ if (cfgFile == null) {
+ cm = new DefaultCacheManager();
+ } else {
+ try {
+ cm = new DefaultCacheManager(cfgFile);
+ } catch (IOException e) {
+ log.errorReadingConfigurationFile(e, cfgFile);
+ cm = new DefaultCacheManager();
+ }
+ }
+ setManager(sce, cm);
+ }
+
+ // Start defined caches to avoid issues with lazily started caches
+ for (String cacheName : cm.getCacheNames())
+ cm.getCache(cacheName);
+
+ // Finally, start default cache as well
+ cm.getCache();
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce) {
+ EmbeddedCacheManager cm = getManager(sce);
+ if (cm != null) {
+ cm.stop();
+ }
+ }
+
+ /**
+ * To avoid any hard dependencies, checking whether the cache manager is injected via the JBoss
+ * MicroContainer is done using reflection.
+ */
+ private EmbeddedCacheManager getMcInjectedCacheManager(ServletContext servletContext) {
+ try {
+ boolean isDebug = log.isDebugEnabled();
+ Object kernel = servletContext.getAttribute("jboss.kernel:service=Kernel");
+ if (kernel != null) {
+ Class<?> kernelCl = loadClass("org.jboss.kernel.Kernel");
+ Object kernelReg = kernelCl.getMethod("getRegistry").invoke(kernel);
+ Class<?> kernelRegCl = loadClass("org.jboss.kernel.spi.registry.KernelRegistry");
+ String beanName = servletContext.getInitParameter("infinispan.cachemanager.bean");
+ if (beanName == null)
+ beanName = "DefaultCacheManager";
+
+ Object kernelRegEntry = kernelRegCl.getMethod("findEntry", Object.class).invoke(kernelReg, beanName);
+ if (kernelRegEntry != null) {
+ Class<?> kernelRegEntryCl = loadClass("org.jboss.kernel.spi.registry.KernelRegistryEntry");
+ if (isDebug)
+ log.debug("Retrieving cache manager from JBoss Microcontainer");
+ return (EmbeddedCacheManager) kernelRegEntryCl.getMethod("getTarget").invoke(kernelRegEntry);
+ } else {
+ if (isDebug)
+ log.debug("Running within JBoss Microcontainer but cache manager bean not present");
+ return null;
+ }
+ }
+ return null;
+ } catch (Exception e) {
+ log.errorRetrievingCacheManagerFromMC(e);
+ return null;
+ }
+ }
+
+ private Class<?> loadClass(String name) throws Exception {
+ return Thread.currentThread().getContextClassLoader().loadClass(name);
+ }
+
+}
@@ -1,113 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009 Red Hat Inc. and/or its affiliates and other
- * contributors as indicated by the @author tags. All rights reserved.
- * See the copyright.txt in the distribution for a full listing of
- * individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.rest
-
-import logging.Log
-import scala.collection.JavaConversions._
-import javax.servlet.http.HttpServlet
-import org.infinispan.manager.{EmbeddedCacheManager, DefaultCacheManager}
-import javax.servlet.ServletConfig
-
-/**
- * To init the cache manager. Nice to do this on startup as any config problems will be picked up before any
- * requests are attempted to be serviced. Less kitten carnage.
- *
- * @author Michael Neale
- * @author Galder Zamarreño
- * @since 4.0
- */
-class StartupListener extends HttpServlet with Log {
- override def init(cfg: ServletConfig) {
- super.init(cfg)
-
- // Check whether the listener is running within an MC environment. A couple of reasons to do this here:
- // 1. REST module is a war file, so a module can't depend on it and compile against it
- // and any module that would want to provide a different listener would need to end up
- // setting ManagerInstance.instance
- // 2. Doing it here makes it a lot easier rather than needing to have a separate module
- // within app server build system
- if (ManagerInstance.instance == null) {
- ManagerInstance.instance = getMcInjectedCacheManager(cfg)
- }
-
- // If cache manager is still null, create one for REST server's own usage
- if (ManagerInstance.instance == null) {
- val cfgFile = cfg getInitParameter "infinispan.config"
- if (cfgFile == null)
- ManagerInstance.instance = new DefaultCacheManager
- else
- ManagerInstance.instance = new DefaultCacheManager(cfgFile)
- }
-
- val cm = ManagerInstance.instance
-
- // Start defined caches to avoid issues with lazily started caches
- for (cacheName <- asScalaIterator(cm.getCacheNames.iterator))
- cm.getCache(cacheName)
-
- // Finally, start default cache as well
- cm.getCache[String, Any]()
- }
-
- override def destroy() {
- super.destroy()
- if (ManagerInstance.instance != null) {
- ManagerInstance.instance.stop()
- }
- ManagerInstance.instance = null
- }
-
- /**
- * To avoid any hard dependencies, checking whether the cache manager is injected
- * via the JBoss MicroContainer is done using reflection.
- */
- private def getMcInjectedCacheManager(cfg: ServletConfig): EmbeddedCacheManager = {
- val isDebug = isDebugEnabled
- val kernel = cfg.getServletContext.getAttribute("jboss.kernel:service=Kernel")
- if (kernel != null) {
- val kernelCl = loadClass("org.jboss.kernel.Kernel")
- val kernelReg = kernelCl.getMethod("getRegistry").invoke(kernel)
- val kernelRegCl = loadClass("org.jboss.kernel.spi.registry.KernelRegistry")
- var beanName = cfg.getInitParameter("infinispan.cachemanager.bean")
- if (beanName == null)
- beanName = "DefaultCacheManager"
-
- val kernelRegEntry = kernelRegCl.getMethod("findEntry", classOf[Object]).invoke(kernelReg, beanName)
- if (kernelRegEntry != null) {
- val kernelRegEntryCl = loadClass("org.jboss.kernel.spi.registry.KernelRegistryEntry")
- if (isDebug) debug("Retrieving cache manager from JBoss Microcontainer")
- return kernelRegEntryCl.getMethod("getTarget").invoke(kernelRegEntry).asInstanceOf[EmbeddedCacheManager]
- } else {
- if (isDebug) debug("Running within JBoss Microcontainer but cache manager bean not present")
- return null
- }
- }
- return null
- }
-
- private def loadClass(name: String): Class[_] = {
- val clazz = Thread.currentThread.getContextClassLoader loadClass name
- clazz.asInstanceOf[Class[_]]
- }
-
-}
@@ -22,6 +22,11 @@
package org.infinispan.rest.logging;
+import static org.jboss.logging.Logger.Level.ERROR;
+
+import org.jboss.logging.Cause;
+import org.jboss.logging.LogMessage;
+import org.jboss.logging.Message;
import org.jboss.logging.MessageLogger;
/**
@@ -33,5 +38,12 @@
*/
@MessageLogger(projectCode = "ISPN")
public interface JavaLog extends org.infinispan.util.logging.Log {
-}
+ @LogMessage(level = ERROR)
+ @Message(value = "Error reading configuration file for REST server: %s", id = 12001)
+ void errorReadingConfigurationFile(@Cause Throwable t, String path);
+
+ @LogMessage(level = ERROR)
+ @Message(value = "Error while retrieving cache manager from JBoss Microcontainer", id = 12002)
+ void errorRetrievingCacheManagerFromMC(@Cause Throwable t);
+}
Oops, something went wrong.

0 comments on commit 77eec93

Please sign in to comment.