Move ShutdownManager into io.ebean.event

This commit is contained in:
rob bygrave committed 2020-10-09 14:13:52 +13:00
1 parent fa4130ba8e
commit 86aed458dd
10 files changed
+45 -67

No files matched your search

@@ -1,65 +0,0 @@
package io.ebeaninternal.api;
/**
* Helper to find classes taking into account the context class loader.
*/
public class ClassUtil {
/**
* Return a new instance of the class using the default constructor.
*/
public static Object newInstance(String className) {
try {
Class<?> cls = forName(className);
return cls.newInstance();
} catch (Exception e) {
String msg = "Error constructing " + className;
throw new IllegalArgumentException(msg, e);
}
}
/**
* Load a class taking into account a context class loader (if present).
*/
public static Class<?> forName(String name) throws ClassNotFoundException {
return new ClassLoadContext().forName(name);
}
/**
* Helper to wrap the context and caller classLoaders (to use/try both).
*/
static class ClassLoadContext {
private final ClassLoader contextLoader;
private final ClassLoader callerLoader;
ClassLoadContext() {
this.callerLoader = ClassUtil.class.getClassLoader();
this.contextLoader = contextLoader();
}
ClassLoader contextLoader() {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
return (loader != null) ? loader : callerLoader;
}
public Class<?> forName(String name) throws ClassNotFoundException {
try {
return Class.forName(name, true, contextLoader);
} catch (ClassNotFoundException e) {
if (callerLoader == contextLoader) {
throw e;
} else {
return Class.forName(name, true, callerLoader);
}
}
}
}
}
@@ -47,11 +47,6 @@ public interface SpiEbeanServer extends ExtendedServer, EbeanServer, BeanCollect
*/
SpiJsonContext jsonExtended();
/**
* For internal use, shutdown of the server invoked by JVM Shutdown.
*/
void shutdownManaged();
/**
* Return true if updates in JDBC batch should include all columns if unspecified on the transaction.
*/
@@ -17,7 +17,7 @@ import io.ebeaninternal.dbmigration.DbOffline;
import io.ebeaninternal.server.cluster.ClusterManager;
import io.ebeaninternal.server.core.bootup.BootupClassPathSearch;
import io.ebeaninternal.server.core.bootup.BootupClasses;
import io.ebeaninternal.server.lib.ShutdownManager;
import io.ebean.event.ShutdownManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -96,7 +96,7 @@ import io.ebeaninternal.server.dto.DtoBeanDescriptor;
import io.ebeaninternal.server.dto.DtoBeanManager;
import io.ebeaninternal.server.el.ElFilter;
import io.ebeaninternal.server.grammer.EqlParser;
import io.ebeaninternal.server.lib.ShutdownManager;
import io.ebean.event.ShutdownManager;
import io.ebeaninternal.server.query.CQuery;
import io.ebeaninternal.server.query.CQueryEngine;
import io.ebeaninternal.server.query.CallableQueryCount;
@@ -300,7 +300,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
configureServerPlugins();
// Register with the JVM Shutdown hook
ShutdownManager.registerEbeanServer(this);
ShutdownManager.registerDatabase(this);
}
/**
@@ -456,11 +456,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
}
/**
* Shutting down via JVM Shutdown hook.
*/
@Override
public void shutdownManaged() {
public void shutdown() {
synchronized (this) {
shutdownInternal(true, false);
}
@@ -473,7 +470,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
public void shutdown(boolean shutdownDataSource, boolean deregisterDriver) {
synchronized (this) {
// Unregister from JVM Shutdown hook
ShutdownManager.unregisterEbeanServer(this);
ShutdownManager.unregisterDatabase(this);
shutdownInternal(shutdownDataSource, deregisterDriver);
}
}
@@ -1,22 +0,0 @@
package io.ebeaninternal.server.lib;
/**
* This is the ShutdownHook that gets added to Runtime.
* It will try to shutdown the system cleanly when the JVM exits.
* It is best to add your own shutdown hooks to StartStop.
*/
class ShutdownHook extends Thread {
ShutdownHook() {
}
/**
* Fired by the JVM Runtime on shutdown.
*/
@Override
public void run() {
ShutdownManager.shutdown();
}
}
@@ -1,200 +0,0 @@
package io.ebeaninternal.server.lib;
import io.ebean.service.SpiContainer;
import io.ebeaninternal.api.ClassUtil;
import io.ebeaninternal.api.SpiEbeanServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* Manages the shutdown of the JVM Runtime.
* <p>
* Makes sure all the resources are shutdown properly and in order.
* </p>
*/
public final class ShutdownManager {
private static final Logger logger = LoggerFactory.getLogger(ShutdownManager.class);
static final List<SpiEbeanServer> servers = new ArrayList<>();
static final ShutdownHook shutdownHook = new ShutdownHook();
static boolean stopping;
static SpiContainer container;
static {
// Register the Shutdown hook
registerShutdownHook();
}
/**
* Disallow construction.
*/
private ShutdownManager() {
}
public static void registerContainer(SpiContainer ebeanContainer) {
container = ebeanContainer;
}
/**
* Make sure the ShutdownManager is activated.
*/
public static void touch() {
// Do nothing
}
/**
* Return true if the system is in the process of stopping.
*/
public static boolean isStopping() {
//noinspection SynchronizationOnStaticField
synchronized (servers) {
return stopping;
}
}
/**
* Deregister the Shutdown hook.
* <p>
* In calling this method it is expected that application code will invoke
* the shutdown() method.
* </p>
* <p>
* For running in a Servlet Container a redeploy will cause a shutdown, and
* for that case we need to make sure the shutdown hook is deregistered.
* </p>
*/
public static void deregisterShutdownHook() {
//noinspection SynchronizationOnStaticField
synchronized (servers) {
try {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
} catch (IllegalStateException ex) {
if (!ex.getMessage().equals("Shutdown in progress")) {
throw ex;
}
}
}
}
/**
* Register the shutdown hook with the Runtime.
*/
protected static void registerShutdownHook() {
//noinspection SynchronizationOnStaticField
synchronized (servers) {
try {
String value = System.getProperty("ebean.registerShutdownHook");
if (value == null || !value.trim().equalsIgnoreCase("false")) {
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
} catch (IllegalStateException ex) {
if (!ex.getMessage().equals("Shutdown in progress")) {
throw ex;
}
}
}
}
/**
* Shutdown gracefully cleaning up any resources as required.
* <p>
* This is typically invoked via JVM shutdown hook.
* </p>
*/
public static void shutdown() {
//noinspection SynchronizationOnStaticField
synchronized (servers) {
if (stopping) {
// Already run shutdown...
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Shutting down");
}
stopping = true;
deregisterShutdownHook();
String shutdownRunner = System.getProperty("ebean.shutdown.runnable");
if (shutdownRunner != null) {
try {
// A custom runnable executed at the start of shutdown
Runnable r = (Runnable) ClassUtil.newInstance(shutdownRunner);
r.run();
} catch (Exception e) {
logger.error("Error running custom shutdown runnable", e);
}
}
if (container != null) {
// shutdown cluster networking if active
container.shutdown();
}
// shutdown any registered servers that have not
// already been shutdown manually
for (SpiEbeanServer server : servers) {
try {
server.shutdownManaged();
} catch (Exception ex) {
logger.error("Error executing shutdown runnable", ex);
ex.printStackTrace();
}
}
if ("true".equalsIgnoreCase(System.getProperty("ebean.datasource.deregisterAllDrivers", "false"))) {
deregisterAllJdbcDrivers();
}
}
}
private static void deregisterAllJdbcDrivers() {
// This manually deregisters all JDBC drivers
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
logger.info("Deregistering jdbc driver: " + driver);
DriverManager.deregisterDriver(driver);
} catch (SQLException e) {
logger.error("Error deregistering driver " + driver, e);
}
}
}
/**
* Register an ebeanServer to be shutdown when the JVM is shutdown.
*/
public static void registerEbeanServer(SpiEbeanServer server) {
//noinspection SynchronizationOnStaticField
synchronized (servers) {
servers.add(server);
}
}
/**
* Deregister an ebeanServer.
* <p>
* This is done when the ebeanServer is shutdown manually.
* </p>
*/
public static void unregisterEbeanServer(SpiEbeanServer server) {
//noinspection SynchronizationOnStaticField
synchronized (servers) {
servers.remove(server);
}
}
}