com.nimbusds.common.servlet.InfinispanLauncher Maven / Gradle / Ivy
Show all versions of common Show documentation
package com.nimbusds.common.servlet;
import java.io.InputStream;
import java.util.Date;
import java.util.concurrent.atomic.AtomicBoolean;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachemanagerlistener.annotation.CacheStarted;
import org.infinispan.notifications.cachemanagerlistener.annotation.CacheStopped;
import org.infinispan.notifications.cachemanagerlistener.event.CacheStartedEvent;
import org.infinispan.notifications.cachemanagerlistener.event.CacheStoppedEvent;
/**
* Configures and launches an Infinispan cache manager at servlet context
* startup. The cache manager is stopped at servlet context shutdown (if
* previously launched).
*
* The location of the Infinispan configuration file in web application
* (WAR) is specified as follows:
*
*
* - By a Java system property {@code infinispan.configurationFile}
*
- By a servlet context init parameter
* {@code infinispan.configurationFile}.
*
*
The launched Infinispan cache manager will be exported to the servlet
* context as an {@code org.infinispan.manager.EmbeddedCacheManager}, under a
* key that bears the interface name.
*/
public class InfinispanLauncher implements ServletContextListener {
/**
* The name of the setting for the Infinispan configuration filename.
*/
public static final String INFINISPAN_CONFIG_FILE_SETTING = "infinispan.configurationFile";
/**
* The name of the servlet context attribute for the launched
* Infinispan cache manager.
*/
public static final String INFINISPAN_CTX_ATTRIBUTE_NAME = "org.infinispan.manager.EmbeddedCacheManager";
/**
* Logs Infinispan status and network topology after startup.
* Thread-safe.
*/
@Listener
public static class StartLogger {
/**
* Startup initiation timestamp.
*/
private final Date initiationTimestamp;
/**
* Cluster info logged status.
*/
private final AtomicBoolean clusterInfoLogged = new AtomicBoolean(false);
/**
* Creates a new Infinispan startup logger.
*
* @param initiationTimestamp The startup initiation timestamp.
* Must not be {@code null}.
*/
public StartLogger(final Date initiationTimestamp) {
this.initiationTimestamp = initiationTimestamp;
}
@CacheStarted
public void logCacheManagerStart(final CacheStartedEvent event) {
Logger log = LogManager.getLogger("MAIN");
EmbeddedCacheManager cacheManager = event.getCacheManager();
if (!cacheManager.getCacheManagerConfiguration().isClustered()) {
// Local Infinispan (no cluster)
log.info("[CM8008] Infinispan clustering: not configured");
} else if (clusterInfoLogged.compareAndSet(false, true)) {
// Clustered Infinispan, log cluster conf for the first start cache event only
// to prevent duplicate log lines with same cluster info
log.info("[CM8007] Infinispan status: {}", cacheManager.getStatus());
log.info("[CM8009] Infinispan cluster name: {}", cacheManager.getCacheManagerConfiguration().transport().clusterName());
log.info("[CM8010] Infinispan cluster local node logical address: {}", cacheManager.getAddress());
log.info("[CM8019] Infinispan cluster local node physical address(es): {}", cacheManager.getCacheManagerConfiguration().transport().transport().getPhysicalAddresses());
log.info("[CM8011] Infinispan cluster coordinator logical address: {}", cacheManager.getCoordinator());
log.info("[CM8016] Infinispan cluster local node is coordinator: {}", cacheManager.isCoordinator());
log.info("[CM8012] Infinispan cluster members: {}", cacheManager.getMembers());
log.info("[CM8013] Infinispan cluster distributed sync timeout: {}", cacheManager.getCacheManagerConfiguration().transport().distributedSyncTimeout());
log.info("[CM8014] Infinispan cluster JGroups configuration file: {}", cacheManager.getCacheManagerConfiguration().transport().properties().getProperty("configurationFile"));
}
final Date now = new Date();
log.info("[CM8006] Started Infinispan {} cache {} in {} ms",
cacheManager.getCacheConfiguration(event.getCacheName()).clustering().cacheModeString(),
event.getCacheName(),
now.getTime() - initiationTimestamp.getTime());
}
}
/**
* Logs Infinispan stop. Thread-safe.
*/
@Listener
public static class StopLogger {
/**
* Shutdown initiation timestamp.
*/
private final Date initiationTimestamp;
/**
* Creates a new Infinispan stop logger.
*
* @param initiationTimestamp The shutdown initiation
* timestamp. Must not be
* {@code null}.
*/
public StopLogger(final Date initiationTimestamp) {
this.initiationTimestamp = initiationTimestamp;
}
@CacheStopped
public void logCacheManagerStop(final CacheStoppedEvent event) {
final Date now = new Date();
final long duration = now.getTime() - initiationTimestamp.getTime();
String msg = "[CM8015] Stopped Infinispan cache " + event.getCacheName() + " in " + duration + " ms";
System.out.println(msg); // Backup logging
LogManager.getLogger("MAIN").info(msg);
}
}
/**
* Reference to the cache manager.
*/
private EmbeddedCacheManager cacheManager;
/**
* Handler for servlet context startup events; configures and launches
* an Infinispan cache manager using the configuration file specified
* in the servlet context parameter {@code infinispan.configurationFile}.
*
*
The configuration file location must be relative to the web
* application directory, e.g. {@code /WEB-INF/infinispan.xml}.
*
*
Exceptions are logged at ERROR level using Log4j.
*
* @param sce A servlet context event.
*/
@Override
public void contextInitialized(final ServletContextEvent sce) {
Logger log = LogManager.getLogger("MAIN");
ServletContext servletContext = sce.getServletContext();
String configFile = System.getProperty(INFINISPAN_CONFIG_FILE_SETTING);
if (StringUtils.isBlank(configFile)) {
configFile = servletContext.getInitParameter(INFINISPAN_CONFIG_FILE_SETTING);
}
LogManager.getLogger("MAIN").info("[CM8000] Starting Infinispan...");
if (StringUtils.isBlank(configFile)) {
String msg = "Couldn't load Infinispan configuration: Missing Java system property or servlet context parameter \"" + INFINISPAN_CONFIG_FILE_SETTING + "\"";
log.error("[CM8001] " + msg);
throw new RuntimeException(msg);
}
log.info("[CM8002] Infinispan configuration file: {}", configFile);
InputStream is = servletContext.getResourceAsStream(configFile);
if (is == null) {
String msg = "Couldn't load Infinispan configuration file: " + configFile;
log.error("[CM8003] " + msg);
throw new RuntimeException(msg);
}
try {
cacheManager = new DefaultCacheManager(is);
} catch (Exception e) {
String msg = "Couldn't start Infinispan cache manager: " + e.getMessage();
log.error("[CM8004] {}" + msg, e);
throw new RuntimeException(msg, e);
}
cacheManager.addListener(new StartLogger(new Date()));
servletContext.setAttribute(INFINISPAN_CTX_ATTRIBUTE_NAME, cacheManager);
}
/**
* Handler for servlet context shutdown events. Stops the Infinispan
* cache manager.
*
* @param sce A servlet context event.
*/
@Override
public void contextDestroyed(final ServletContextEvent sce) {
Logger log = LogManager.getLogger("MAIN");
if (cacheManager == null) {
String msg = "[CM8017] Infinispan cache manager not initialised";
log.error(msg);
throw new IllegalStateException(msg);
}
String msg = "[CM8005] Stopping Infinispan...";
System.out.println(msg); // Backup logging, see https://bitbucket.org/connect2id/server/issues/164/infinispan-shutdown-not-logged
log.info(msg);
cacheManager.addListener(new StopLogger(new Date()));
cacheManager.stop();
}
}