[java-shib-shared] 03/09: JSSH-71 Remove the impact of the DestructableComponent Interface

Codeberg noreply at shibboleth.net
Thu Jul 9 10:48:37 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository java-shib-shared.

View the commit online:
https://codeberg.org/Shibboleth/java-shib-shared/commit/1243979fd66dd1613e48a90c2f9204933b892492

commit 1243979fd66dd1613e48a90c2f9204933b892492
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Mon Jul 6 14:47:18 2026 +0100

    JSSH-71 Remove the impact of the DestructableComponent Interface
    
    https://shibboleth.atlassian.net/browse/JSSH-71
    
    Add the hooks into AbstractServiceableComponent to tear down the previous
    objects when the component goes away.
---
 .../shared/spring/service/AbstractServiceableComponent.java   | 11 ++++++++++-
 .../shared/spring/service/ReloadableSpringServiceTest.java    |  9 ++++++---
 .../shared/spring/service/TestServiceableComponent.java       |  6 ++++++
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/shib-service/src/main/java/net/shibboleth/shared/spring/service/AbstractServiceableComponent.java b/shib-service/src/main/java/net/shibboleth/shared/spring/service/AbstractServiceableComponent.java
index 68ad231c..1c5ca2e8 100644
--- a/shib-service/src/main/java/net/shibboleth/shared/spring/service/AbstractServiceableComponent.java
+++ b/shib-service/src/main/java/net/shibboleth/shared/spring/service/AbstractServiceableComponent.java
@@ -20,13 +20,14 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
-
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.ConfigurableApplicationContext;
 
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.primitive.AnnotationsSupport;
 import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.service.ServiceableComponent;
 
@@ -119,11 +120,19 @@ public abstract class AbstractServiceableComponent<T> extends AbstractIdentifiab
 
         if (null != oldContext) {
             log.debug("Component '{}': Closing the appcontext", getId());
+            // This is where the magic happens.  Call the teardown on any bean with a teardown
+            // method. Acts alongside the spring lifecycle
+            ConfigurableListableBeanFactory clbf = oldContext.getBeanFactory();
+            for (final String beanName :oldContext.getBeanDefinitionNames()) {
+                final Object bean = clbf.getSingleton(beanName);
+                AnnotationsSupport.callOnTeardownAnnotations(bean, beanName, log);
+            }
             oldContext.close();
         }
         // If we were not created by spring we need to do the destroy of ourself.
         // Note that we will end up being called here but will fall out at the top.
         destroy();
+        AnnotationsSupport.callOnTeardownAnnotations(this, getId(), log);
     }
 
     /** {@inheritDoc} */
diff --git a/shib-service/src/test/java/net/shibboleth/shared/spring/service/ReloadableSpringServiceTest.java b/shib-service/src/test/java/net/shibboleth/shared/spring/service/ReloadableSpringServiceTest.java
index a5ef2faa..157f6e13 100644
--- a/shib-service/src/test/java/net/shibboleth/shared/spring/service/ReloadableSpringServiceTest.java
+++ b/shib-service/src/test/java/net/shibboleth/shared/spring/service/ReloadableSpringServiceTest.java
@@ -101,11 +101,12 @@ public class ReloadableSpringServiceTest {
         overwriteFileWith("net/shibboleth/shared/spring/service/ServiceableBean2.xml");
 
         long count = 70;
-        while (count > 0 && !component.isDestroyed()) {
+        while (count > 0 && !component.isDestroyed() && !component.tornDown) {
             Thread.sleep(RELOAD_DELAY.toMillis());
             count--;
         }
         Assert.assertTrue(component.isDestroyed(), "After 7 second initial component has still not be destroyed");
+        Assert.assertTrue(component.tornDown, "After 7 second initial component has still not been torn down");
 
         //
         // The reload will have destroyed the old component
@@ -117,7 +118,6 @@ public class ReloadableSpringServiceTest {
 
         Assert.assertEquals(serviceableComponent.getComponent().getTheValue(), "Two");
         serviceableComponent.unpinComponent();
-        service.destroy();
         
         deleteFile();
     }
@@ -145,6 +145,7 @@ public class ReloadableSpringServiceTest {
 
         Assert.assertEquals(component.getTheValue(), "One");
         Assert.assertFalse(component.isDestroyed());
+        Assert.assertFalse(component.tornDown);
 
         Thread.sleep(RELOAD_DELAY.toMillis() * 3);
         Assert.assertEquals(x,  service.getLastReloadAttemptInstant());
@@ -155,6 +156,7 @@ public class ReloadableSpringServiceTest {
         // The reload will not have destroyed the old component yet
         //
         Assert.assertFalse(component.isDestroyed());
+        Assert.assertFalse(component.tornDown);
 
         long count = 70;
         TestServiceableComponent component2 = null;
@@ -173,11 +175,12 @@ public class ReloadableSpringServiceTest {
         Assert.assertNotNull(component2, "After 7 second initial component has still not got new value");
     
         count = 70;
-        while (count > 0 && !component.isDestroyed()) {
+        while (count > 0 && !component.isDestroyed() && !component.tornDown) {
             Thread.sleep(RELOAD_DELAY.toMillis());
             count--;
         }
         Assert.assertTrue(component.isDestroyed(), "After 7 second initial component has still not be destroyed");
+        Assert.assertTrue(component.tornDown, "After 7 second initial component has still not been torn down");
         service.destroy();
         deleteFile();
     }
diff --git a/shib-service/src/test/java/net/shibboleth/shared/spring/service/TestServiceableComponent.java b/shib-service/src/test/java/net/shibboleth/shared/spring/service/TestServiceableComponent.java
index 44f1c12b..1012d1ae 100644
--- a/shib-service/src/test/java/net/shibboleth/shared/spring/service/TestServiceableComponent.java
+++ b/shib-service/src/test/java/net/shibboleth/shared/spring/service/TestServiceableComponent.java
@@ -14,6 +14,7 @@
 
 package net.shibboleth.shared.spring.service;
 
+import net.shibboleth.shared.annotation.OnTeardown;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 
 @SuppressWarnings("javadoc")
@@ -21,6 +22,7 @@ public class TestServiceableComponent extends AbstractIdentifiableInitializableC
 
     private String theValue;
     
+    public boolean tornDown;
 
     /**
      * @return Returns the theValue.
@@ -36,4 +38,8 @@ public class TestServiceableComponent extends AbstractIdentifiableInitializableC
         theValue = value;
     }
 
+    @OnTeardown public void teardown() {
+        tornDown = true;
+    }
+
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list