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

Codeberg noreply at shibboleth.net
Thu Jul 9 10:48:35 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/26cce6aa0d3e4926667d44884cf80074b1852f1a

commit 26cce6aa0d3e4926667d44884cf80074b1852f1a
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Mon Jul 6 14:22:48 2026 +0100

    JSSH-71 Remove the impact of the DestructableComponent Interface
    
    https://shibboleth.atlassian.net/browse/JSSH-71
    
    New private annotation (OnTeardown) targeted at replacing the doDestroy
    methods that actually did anything.
---
 .../shibboleth/shared/annotation/OnTeardown.java   |  36 ++++++++
 .../shared/primitive/AnnotationsSupport.java       |  90 ++++++++++++++++++
 .../shared/primitive/AnnotationsSupportTest.java   | 102 +++++++++++++++++++++
 3 files changed, 228 insertions(+)

diff --git a/shib-support/src/main/java/net/shibboleth/shared/annotation/OnTeardown.java b/shib-support/src/main/java/net/shibboleth/shared/annotation/OnTeardown.java
new file mode 100644
index 00000000..2c512099
--- /dev/null
+++ b/shib-support/src/main/java/net/shibboleth/shared/annotation/OnTeardown.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.shared.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Identifies a method to be called when a object is removed from service
+ *
+ * <p>Methods marked like this should have zero parameters and be marked final, so as to prevent tear down
+ * methods at different levels of the object hierarchy getting in each others way</p>
+ *
+ * @since 9.3.0
+ */
+ at Documented
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD, })
+public @interface OnTeardown {
+
+}
\ No newline at end of file
diff --git a/shib-support/src/main/java/net/shibboleth/shared/primitive/AnnotationsSupport.java b/shib-support/src/main/java/net/shibboleth/shared/primitive/AnnotationsSupport.java
new file mode 100644
index 00000000..fdfda24b
--- /dev/null
+++ b/shib-support/src/main/java/net/shibboleth/shared/primitive/AnnotationsSupport.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.shared.primitive;
+
+import java.lang.reflect.Method;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+
+import net.shibboleth.shared.annotation.OnTeardown;
+import net.shibboleth.shared.component.IdentifiedComponent;
+
+
+/**
+ * Static methods to work with annotations.
+ */
+public final class AnnotationsSupport {
+
+    /** Call the {@link @OnTeardown} methods.
+     * @param obj The object to introspect
+     * @param id The id of the object
+     * @param log the logger to use
+     */
+    static public void callOnTeardownAnnotations(@Nullable final Object obj, @Nullable final String id, @Nullable final Logger log) {
+
+        Logger theLog = log;
+        String theName = id;
+        if (obj == null) {
+            return;
+        }
+        for (final Method m: obj.getClass().getMethods()) {
+            if (m.getParameterCount() == 0 && m.getAnnotation(OnTeardown.class) != null) {
+                if (theName == null) {
+                    if (obj instanceof IdentifiedComponent) {
+                        theName = ((IdentifiedComponent)obj).getId();
+                    }
+                    if (theName == null) {
+                        theName = "Unidentified bean of type " + obj.getClass().getName();
+                    }
+                }
+                if (log != null) {
+                    log.debug("{}: found a PreDestroyMethod {}", id, m);
+                }
+                try {
+                    m.invoke(obj);
+                } catch (final Exception e) {
+                    if (theLog == null) {
+                        theLog = LoggerFactory.getLogger(AnnotationsSupport.class);
+                    }
+                    theLog.error("{}: Failed invoking {}", id, m, e);
+                }
+            }
+        }
+    }
+    /** Call the {@link @PreDestroy} methods.
+     * @param obj The object to introspect
+     */
+    static public void callOnTeardownAnnotations(@Nullable final Object obj) {
+        callOnTeardownAnnotations(obj, null, null);
+    }
+    /** Mostly for testing - does this object carry a {@link @PreDestroy} annotated
+     * method?
+     * @param obj The object to introspect
+     * @return whether it is tear-downable.
+     */
+    static public boolean hasPreDestroyAnnotation(@Nullable final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        for (final Method m: obj.getClass().getMethods()) {
+            if (m.getParameterCount() == 0 && m.getAnnotation(OnTeardown.class) != null) {
+                return true;
+            }
+        }
+        return false;
+     }
+}
diff --git a/shib-support/src/test/java/net/shibboleth/shared/primitive/AnnotationsSupportTest.java b/shib-support/src/test/java/net/shibboleth/shared/primitive/AnnotationsSupportTest.java
new file mode 100644
index 00000000..b7f575f2
--- /dev/null
+++ b/shib-support/src/test/java/net/shibboleth/shared/primitive/AnnotationsSupportTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.shared.primitive;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.shared.annotation.OnTeardown;
+
+/** Tests for {@link AnnotationsSupport}.  */
+public class AnnotationsSupportTest {
+
+    private boolean withCalled;
+    private boolean withDerivedCalled;
+    private boolean withParamCalled;
+
+    @BeforeMethod public void reset() {
+        withCalled = false;
+        withParamCalled = false;
+        withDerivedCalled = false;
+    }
+
+    @Test public void withTest() {
+        final var what = new With();
+        assertTrue(AnnotationsSupport.hasPreDestroyAnnotation(what));
+        AnnotationsSupport.callOnTeardownAnnotations(what);
+        assertTrue(withCalled);
+        assertFalse(withParamCalled);
+        assertFalse(withDerivedCalled);
+    }
+
+    @Test public void withParamTest() {
+        final var what = new WithParam();
+        assertFalse(AnnotationsSupport.hasPreDestroyAnnotation(what));
+        AnnotationsSupport.callOnTeardownAnnotations(what);
+        assertFalse(withCalled);
+        assertFalse(withDerivedCalled);
+        assertFalse(withParamCalled);
+    }
+    
+    @Test public void withDerivedTest() {
+        final var what = new WithDerived();
+        assertTrue(AnnotationsSupport.hasPreDestroyAnnotation(what));
+        AnnotationsSupport.callOnTeardownAnnotations(what);
+        assertTrue(withCalled);
+        assertTrue(withDerivedCalled);
+        assertFalse(withParamCalled);
+    }
+
+
+    @Test public void withOutTest() {
+        final var what = new Without();
+        assertFalse(AnnotationsSupport.hasPreDestroyAnnotation(what));
+        AnnotationsSupport.callOnTeardownAnnotations(what);
+        assertFalse(withCalled);
+        assertFalse(withDerivedCalled);
+        assertFalse(withParamCalled);
+    }
+
+    private class With {
+
+        @OnTeardown public final void teardown() {
+            withCalled = true;
+        }
+    }
+    
+    private class WithDerived extends With {
+        
+        @OnTeardown public final void t2() {
+            withDerivedCalled = true;
+        }
+    }
+
+    private class WithParam {
+
+        @OnTeardown public final void teardown(final int param) {
+            withParamCalled = true;
+        }
+    }
+
+    private class Without {
+
+        @SuppressWarnings("unused")
+        public final void teardown() {
+        }
+    }
+}

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


More information about the commits mailing list