I have a stupid answer but I'll show you what I did.
@JulienR: I already had the shutdown=true in my persistence.xml file for the javax.persistence.jdbc.url value.
I created a ServletContextListener and added it to my web.xml file; here's the code. The first part that uses the EntityManager to issue the SHUTDOWN command is my code. The code for the ClassLoader and driver eyeballing I got off of here. So with this it's no longer complaining about HSQLDB but I'm still getting a WARNING about two threads that weren't stopped (and I have to wait for eclipse to time out waiting for it). I've appended the relevant lines from the log.
public class BasicServletContextListener implements ServletContextListener {
private final transient Logger log =
LoggerFactory.getLogger(BasicServletContextListener.class);
// private final Provider<EntityManager> entityManagerProvider;
@Override
public void contextDestroyed(ServletContextEvent event) {
this.log.debug("contextEvent: {}", event.toString());
final EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("ilmp");
final EntityManager entityManager =
entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
final Query query =
entityManager.createNativeQuery("SHUTDOWN COMPACT;");
this.log.debug("query: {}", query.executeUpdate());
entityManager.getTransaction().commit();
entityManager.close();
// Now deregister JDBC drivers in this context's ClassLoader:
// Get the webapp's ClassLoader
final ClassLoader cl = Thread.currentThread().getContextClassLoader();
// Loop through all drivers
final Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
final Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
// This driver was registered by the webapp's
// ClassLoader, so deregister it:
try {
this.log.info("Deregistering JDBC driver {}", driver);
DriverManager.deregisterDriver(driver);
}
catch (final SQLException ex) {
this.log.error("Error deregistering JDBC driver {}", driver,
ex);
}
}
else {
// driver was not registered by the webapp's
// ClassLoader and may be in use elsewhere
this.log.trace(
"Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader",
driver);
}
}
}
@Override
public void contextInitialized(ServletContextEvent event) {
this.log.debug("contextEvent: {}", event.toString());
}
}
>
INFO: 2017-Feb-01 19:05:36.023 [localhost-startStop-2] org.hibernate.hql.internal.QueryTranslatorFactoryInitiator.initiateService.47: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: SHUTDOWN COMPACT;
INFO: 2017-Feb-01 19:05:36.226 [localhost-startStop-2] sun.reflect.NativeMethodAccessorImpl.invoke0.-2: Database closed
INFO: 2017-Feb-01 19:05:36.273 [localhost-startStop-2] sun.reflect.NativeMethodAccessorImpl.invoke0.-2: open start - state not modified
INFO: 2017-Feb-01 19:05:36.351 [localhost-startStop-2] sun.reflect.NativeMethodAccessorImpl.invoke0.-2: Database closed
DEBUG: 2017-Feb-01 19:05:36.460 [localhost-startStop-2] com.objecteffects.basic.persist.BasicServletContextListener.contextDestroyed.42: query: 0
INFO: 2017-Feb-01 19:05:36.460 [localhost-startStop-2] com.objecteffects.basic.persist.BasicServletContextListener.contextDestroyed.59: Deregistering JDBC driver org.hsqldb.jdbc.JDBCDriver@3cd32e8d
Feb 01, 2017 7:05:36 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [basic] appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
Feb 01, 2017 7:05:36 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [basic] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
Feb 01, 2017 7:05:36 PM org.apache.catalina.loader.WebappClassLoaderBase checkThreadLocalMapForLeaks
SEVERE: The web application [basic] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@1bc6eba0]) and a value of type [org.hibernate.internal.SessionImpl] (value [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.objecteffects.basic.persist.TumblrSecretsEntity#1], EntityKey[com.objecteffects.basic.persist.TumblrSecretsEntity#2]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
Feb 01, 2017 7:05:36 PM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["http-nio-8080"]
Feb 01, 2017 7:05:36 PM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["ajp-nio-8009"]
Feb 01, 2017 7:05:36 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-nio-8080"]
Feb 01, 2017 7:05:36 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["ajp-nio-8009"]
The stupid answer is that I looked at my setup for something I wrote several years ago (I'm retired and just dinking around trying to write something for myself) and adding the c3p0 config lines I'd used previously to this persistence.xml makes it shut down without the delay, although I still get a bunch of warnings about zombie threads. Here are the relevant lines (still commented out).
<!-- <property -->
<!-- name="hibernate.c3p0.min_size" -->
<!-- value="5" /> -->
<!-- <property -->
<!-- name="hibernate.c3p0.max_size" -->
<!-- value="20" /> -->
<!-- <property -->
<!-- name="hibernate.c3p0.timeout" -->
<!-- value="1800" /> -->
<!-- <property -->
<!-- name="hibernate.c3p0.max_statements" -->
<!-- value="50" /> -->