You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rz...@apache.org on 2026/04/23 13:50:46 UTC

(tomee) 08/23: security/cdi: dedupe mechanism definitions collected in ProcessBean

This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch security-4.0
in repository https://gitbox.apache.org/repos/asf/tomee.git

commit 14e5173ff75900003d1e40a8126ea32f6853dfe3
Author: Richard Zowalla <rz...@apache.org>
AuthorDate: Mon Apr 20 20:32:14 2026 +0200

    security/cdi: dedupe mechanism definitions collected in ProcessBean
    
    ProcessBean can fire more than once for the same annotated type
    (e.g. when CDI synthesises observer/interceptor beans on it), so
    List.addAll accumulated duplicate @*AuthenticationMechanismDefinition
    instances. After c723b38920 started registering one bean per
    collected definition, this produced multiple beans with identical
    qualifier sets and AmbiguousResolutionException on startup -- the
    tomee-security servlet tests failed to deploy.
    
    Switch the four *MechanismDefinitions collections to LinkedHashSet
    (annotations are value-equal) and snapshot them to ordered lists at
    AfterBeanDiscovery time so the indexed bean-id scheme still works.
    
    Also update OpenIdAuthenticationMechanismUnitTest to set the
    definition through the supplier hook rather than reflecting into a
    field that no longer exists.
---
 .../tomee/security/cdi/TomEESecurityExtension.java | 23 ++++++++++++++++++----
 .../cdi/OpenIdAuthenticationMechanismUnitTest.java |  2 +-
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java
index 00656eaa5b..79358d428b 100644
--- a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java
+++ b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java
@@ -60,15 +60,20 @@ import jakarta.security.enterprise.identitystore.LdapIdentityStoreDefinition;
 
 import java.lang.annotation.Annotation;
 import java.util.ArrayList;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Supplier;
 
 public class TomEESecurityExtension implements Extension {
-    private final List<BasicAuthenticationMechanismDefinition> basicMechanismDefinitions = new ArrayList<>();
-    private final List<FormAuthenticationMechanismDefinition> formMechanismDefinitions = new ArrayList<>();
-    private final List<CustomFormAuthenticationMechanismDefinition> customMechanismDefinitions = new ArrayList<>();
-    private final List<OpenIdAuthenticationMechanismDefinition> oidcMechanismDefinitions = new ArrayList<>();
+    // LinkedHashSet: ProcessBean fires for each bean *and* any derived observer/interceptor beans on the
+    // same class, so List.addAll would otherwise duplicate identical annotation instances and cause
+    // AmbiguousResolutionException when multiple beans are registered with the same qualifier set.
+    private final Set<BasicAuthenticationMechanismDefinition> basicMechanismDefinitions = new LinkedHashSet<>();
+    private final Set<FormAuthenticationMechanismDefinition> formMechanismDefinitions = new LinkedHashSet<>();
+    private final Set<CustomFormAuthenticationMechanismDefinition> customMechanismDefinitions = new LinkedHashSet<>();
+    private final Set<OpenIdAuthenticationMechanismDefinition> oidcMechanismDefinitions = new LinkedHashSet<>();
 
     private final AtomicReference<Annotated> tomcatUserStore = new AtomicReference<>();
     private final AtomicReference<Annotated> databaseStore = new AtomicReference<>();
@@ -129,6 +134,16 @@ public class TomEESecurityExtension implements Extension {
         @Observes final AfterBeanDiscovery afterBeanDiscovery,
         final BeanManager beanManager) {
 
+        // Snapshot definition sets as ordered lists so the registration loops can use index-based IDs.
+        final List<BasicAuthenticationMechanismDefinition> basicMechanismDefinitions =
+                new ArrayList<>(this.basicMechanismDefinitions);
+        final List<FormAuthenticationMechanismDefinition> formMechanismDefinitions =
+                new ArrayList<>(this.formMechanismDefinitions);
+        final List<CustomFormAuthenticationMechanismDefinition> customMechanismDefinitions =
+                new ArrayList<>(this.customMechanismDefinitions);
+        final List<OpenIdAuthenticationMechanismDefinition> oidcMechanismDefinitions =
+                new ArrayList<>(this.oidcMechanismDefinitions);
+
         if (tomcatUserStore.get() != null) {
             afterBeanDiscovery
                 .addBean()
diff --git a/tomee/tomee-security/src/test/java/org/apache/tomee/security/cdi/OpenIdAuthenticationMechanismUnitTest.java b/tomee/tomee-security/src/test/java/org/apache/tomee/security/cdi/OpenIdAuthenticationMechanismUnitTest.java
index 2c3df3989e..0626cf0ed9 100644
--- a/tomee/tomee-security/src/test/java/org/apache/tomee/security/cdi/OpenIdAuthenticationMechanismUnitTest.java
+++ b/tomee/tomee-security/src/test/java/org/apache/tomee/security/cdi/OpenIdAuthenticationMechanismUnitTest.java
@@ -59,7 +59,7 @@ public class OpenIdAuthenticationMechanismUnitTest {
         identityStoreHandler = mock(IdentityStoreHandler.class);
         storageHandler = new SimpleStorageHandler();
 
-        Reflections.set(authenticationMechanism, "definition", definition);
+        authenticationMechanism.setDefinitionSupplier(() -> definition);
         Reflections.set(authenticationMechanism, "identityStoreHandler", identityStoreHandler);
         Reflections.set(authenticationMechanism, "openIdContext", new TomEEOpenIdContext());
         Reflections.set(authenticationMechanism, "storageHandler", storageHandler);