My app does a clean shutdown by calling XMPPServer.stop() but some components 
are starting threads and not cleaning them up. One of these that I have found 
is MemoryOfflineStorageProvider. I’ve added a close() hook to StorageProvider 
and implemented it in all of the storage providers and made the implementation 
in MemoryOfflineStorageProvider clean up the thread it creates. Then in my app 
I iterate over all of the StorageProvider instances and call close(). A better 
way to do this is not obvious to me.

diff --git 
a/server/core/src/main/java/org/apache/vysper/storage/StorageProvider.java 
b/server/core/src/main/java/org/apache/vysper/storage/StorageProvider.java
index e5245fa..fd7e791 100644
--- a/server/core/src/main/java/org/apache/vysper/storage/StorageProvider.java
+++ b/server/core/src/main/java/org/apache/vysper/storage/StorageProvider.java
@@ -25,4 +25,10 @@ package org.apache.vysper.storage;
  * @author The Apache MINA Project ([email protected])
  */
 public interface StorageProvider {
+
+    /**
+     * Allow for the storage provider to release any resources held, for 
example database connections.
+     */
+    void close();
+
 }
diff --git 
a/server/core/src/main/java/org/apache/vysper/xmpp/authentication/SimpleUserAuthentication.java
 
b/server/core/src/main/java/org/apache/vysper/xmpp/authentication/SimpleUserAuthentication.java
index aca5a9c..5026166 100644
--- 
a/server/core/src/main/java/org/apache/vysper/xmpp/authentication/SimpleUserAuthentication.java
+++ 
b/server/core/src/main/java/org/apache/vysper/xmpp/authentication/SimpleUserAuthentication.java
@@ -63,4 +63,8 @@ public class SimpleUserAuthentication implements 
UserAuthentication, AccountMana
     private boolean verify(Entity username, String passwordCleartext) {
         return passwordCleartext.equals(userPasswordMap.get(username));
     }
+
+    @Override
+    public void close() {
+    }
 }
diff --git 
a/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0160_offline_storage/AbstractOfflineStorageProvider.java
 
b/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0160_offline_storage/AbstractOfflineStorageProvider.java
index 97a49a8..967b7b0 100644
--- 
a/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0160_offline_storage/AbstractOfflineStorageProvider.java
+++ 
b/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0160_offline_storage/AbstractOfflineStorageProvider.java
@@ -86,4 +86,9 @@ public abstract class AbstractOfflineStorageProvider 
implements OfflineStoragePr
     /** does the actual storage mechanism */
     protected abstract void storeStanza(Stanza stanza);
 
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
+
 }
diff --git 
a/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0160_offline_storage/MemoryOfflineStorageProvider.java
 
b/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0160_offline_storage/MemoryOfflineStorageProvider.java
index 0191647..ff8838f 100644
--- 
a/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0160_offline_storage/MemoryOfflineStorageProvider.java
+++ 
b/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0160_offline_storage/MemoryOfflineStorageProvider.java
@@ -44,6 +44,8 @@ public class MemoryOfflineStorageProvider extends 
AbstractOfflineStorageProvider
 
     private Map<String, List<Entry>> offlineStorageMap = new HashMap<String, 
List<Entry>>();
 
+    private final Timer timer = new Timer("OfflineTimeoutCheckerTimer", true);
+
     public MemoryOfflineStorageProvider() {
         this(7 * 24 * 3600 * 1000); // default to seven days;
     }
@@ -53,7 +55,6 @@ public class MemoryOfflineStorageProvider extends 
AbstractOfflineStorageProvider
         int period = 60 * 100 * 1000;
 
         this.timeout = timeout;
-        Timer timer = new Timer("OfflineTimeoutCheckerTimer", true);
         timer.schedule(new TimeoutChecker(), delay, period);
     }
 
@@ -88,6 +89,12 @@ public class MemoryOfflineStorageProvider extends 
AbstractOfflineStorageProvider
         }
     }
 
+    @Override
+    public void close() {
+        timer.cancel();
+        super.close();
+    }
+
     private static class Entry {
 
         private Stanza stanza;
diff --git 
a/server/core/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/AbstractRosterManager.java
 
b/server/core/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/AbstractRosterManager.java
index 8f7c2a2..c7178bc 100644
--- 
a/server/core/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/AbstractRosterManager.java
+++ 
b/server/core/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/AbstractRosterManager.java
@@ -76,4 +76,9 @@ public abstract class AbstractRosterManager implements 
RosterManager, ServerRunt
     public String getServiceName() {
         return RosterManager.SERVER_SERVICE_ROSTERMANAGER;
     }
+
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
 }
diff --git 
a/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/storage/InMemoryOccupantStorageProvider.java
 
b/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/storage/InMemoryOccupantStorageProvider.java
index 0b32b1e..caa7b37 100644
--- 
a/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/storage/InMemoryOccupantStorageProvider.java
+++ 
b/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/storage/InMemoryOccupantStorageProvider.java
@@ -40,4 +40,9 @@ public class InMemoryOccupantStorageProvider implements 
OccupantStorageProvider
         // do nothing
     }
 
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
+
 }
diff --git 
a/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/storage/InMemoryRoomStorageProvider.java
 
b/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/storage/InMemoryRoomStorageProvider.java
index bdde7b5..fc732ca 100644
--- 
a/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/storage/InMemoryRoomStorageProvider.java
+++ 
b/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/storage/InMemoryRoomStorageProvider.java
@@ -68,4 +68,9 @@ public class InMemoryRoomStorageProvider implements 
RoomStorageProvider {
 
     }
 
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
+
 }
diff --git 
a/server/extensions/xep0060-pubsub/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeInMemoryStorageProvider.java
 
b/server/extensions/xep0060-pubsub/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeInMemoryStorageProvider.java
index 31e91e5..114b692 100644
--- 
a/server/extensions/xep0060-pubsub/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeInMemoryStorageProvider.java
+++ 
b/server/extensions/xep0060-pubsub/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/CollectionNodeInMemoryStorageProvider.java
@@ -91,4 +91,9 @@ public class CollectionNodeInMemoryStorageProvider implements 
CollectionNodeStor
         n.delete();
         this.nodes.remove(nodeName);
     }
+
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
 }
diff --git 
a/server/extensions/xep0060-pubsub/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java
 
b/server/extensions/xep0060-pubsub/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java
index 0755637..43eb3f0 100644
--- 
a/server/extensions/xep0060-pubsub/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java
+++ 
b/server/extensions/xep0060-pubsub/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0060_pubsub/storageprovider/LeafNodeInMemoryStorageProvider.java
@@ -238,4 +238,9 @@ public class LeafNodeInMemoryStorageProvider implements 
LeafNodeStorageProvider
             mav.visit(jid, affil);
         }
     }
+
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
 }
diff --git 
a/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/privatedata/HBasePrivateDataPersistenceManager.java
 
b/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/privatedata/HBasePrivateDataPersistenceManager.java
index 322bb77..be3b07f 100644
--- 
a/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/privatedata/HBasePrivateDataPersistenceManager.java
+++ 
b/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/privatedata/HBasePrivateDataPersistenceManager.java
@@ -52,4 +52,8 @@ public class HBasePrivateDataPersistenceManager extends 
HBaseGenericXEPDataManag
         return setValue(entity, key, xml);
     }
 
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
 }
diff --git 
a/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/user/HBaseUserManagement.java
 
b/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/user/HBaseUserManagement.java
index e98c019..1c03a35 100644
--- 
a/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/user/HBaseUserManagement.java
+++ 
b/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/user/HBaseUserManagement.java
@@ -149,4 +149,9 @@ public class HBaseUserManagement implements 
UserAuthentication, AccountManagemen
             throw new AccountCreationException("failed to change password for 
" + username, e);
         }
     }
+
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
 }
diff --git 
a/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/vcard/HBaseVcardTempPersistenceManager.java
 
b/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/vcard/HBaseVcardTempPersistenceManager.java
index 550f8af..12505e6 100644
--- 
a/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/vcard/HBaseVcardTempPersistenceManager.java
+++ 
b/server/storage/hbase/src/main/java/org/apache/vysper/storage/hbase/vcard/HBaseVcardTempPersistenceManager.java
@@ -53,4 +53,9 @@ public class HBaseVcardTempPersistenceManager extends 
HBaseGenericXEPDataManager
     public boolean setVcard(Entity entity, String xml) {
         return setValue(entity, KEY, xml);
     }
+
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
 }
diff --git 
a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
 
b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
index 6a7544d..3deb397 100644
--- 
a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
+++ 
b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
@@ -88,4 +88,9 @@ public class JcrPrivateDataPersistenceManager implements 
PrivateDataPersistenceM
             return null;
         return entityNode;
     }
+
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
 }
diff --git 
a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
 
b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
index 0f5da9f..69fb05e 100644
--- 
a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
+++ 
b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
@@ -115,4 +115,9 @@ public class JcrUserManagement implements 
UserAuthentication, AccountManagement
             throw new AccountCreationException("failed to create the account 
set credentials", e);
         }
     }
+
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
 }
diff --git 
a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
 
b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
index 293bad5..f1152d0 100644
--- 
a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
+++ 
b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
@@ -89,4 +89,10 @@ public class JcrVcardTempPersistenceManager implements 
VcardTempPersistenceManag
             return false;
         }
     }
+
+    @Override
+    public void close() {
+        // This implementation does not need to do anything to close. 
Subclasses should override and call super.close().
+    }
+
 }

Reply via email to