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(). + } + }
