From 5b2a51491b8f935245c6dd2f49c61fd06e0c4dc4 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Wed, 6 Dec 2023 13:40:30 +0100 Subject: [PATCH] ArC: prevent duplicate bean discovery & detect duplicate bean identifiers A bean class may occur in the bean archive index multiple times, because the index is in fact a composite of multiple indices and there's nothing preventing duplicity in the composition. Fortunately, all the additional customizations (such as default scope or unremovability from `AdditionalBeanBuildItem`) are passed around outside of the bean archive index (for example, as annotation transformations or as `BeanProcessor` configuration), so they are not lost. --- .../quarkus/arc/processor/BeanDeployment.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java index 1ea3ad5b3bf49..e96bbbe6df310 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java @@ -956,8 +956,14 @@ private List findBeans(Collection beanDefiningAnnotations, Li .map(StereotypeInfo::getName) .collect(Collectors.toSet()); + Set seenClasses = new HashSet<>(); + // If needed use the specialized immutable index to discover beans for (ClassInfo beanClass : beanArchiveImmutableIndex.getKnownClasses()) { + if (!seenClasses.add(beanClass.name())) { + // avoid discovering the same bean twice + continue; + } if (Modifier.isInterface(beanClass.flags()) || Modifier.isAbstract(beanClass.flags()) || beanClass.isAnnotation() || beanClass.isEnum()) { @@ -1583,6 +1589,29 @@ private void validateBeans(List errors, Consumer } } } + + List>> duplicateBeanIds = beans.stream() + .collect(Collectors.groupingBy(BeanInfo::getIdentifier)) + .entrySet() + .stream() + .filter(entry -> entry.getValue().size() > 1) + .collect(Collectors.toList()); + if (!duplicateBeanIds.isEmpty()) { + String separator = "===================="; + StringBuilder error = new StringBuilder("\n") + .append(separator).append(separator).append(separator).append(separator).append("\n") + .append("Multiple beans with the same identifier found!\n") + .append("----------------------------------------------\n") + .append("This is an internal error. Please report a bug and attach the following listing.\n\n"); + for (Map.Entry> entry : duplicateBeanIds) { + error.append(entry.getKey()).append(" -> ").append(entry.getValue().size()).append(" beans:\n"); + for (BeanInfo bean : entry.getValue()) { + error.append("- ").append(bean).append("\n"); + } + } + error.append(separator).append(separator).append(separator).append(separator).append("\n"); + errors.add(new DeploymentException(error.toString())); + } } private void findNamespaces(BeanInfo bean, Set namespaces) {