Exclude HttpServiceClient from GroupRegistry scan

The detect methods in the GroupRegistry that find all interfaces
with HttpExchange annotations now exclude HttpServiceClient
interfaces that are instead supported by a dedicated registrar.

This ensures there is no overlap between the HttpServiceClient
registrar scan and the ImportHttpServices registrar scan or
the scan of any other custom registrar.

See gh-35244
This commit is contained in:
rstoyanchev
2025-07-31 05:22:06 +01:00
parent 09917fad7b
commit 0fc9e4ec1c
6 changed files with 37 additions and 16 deletions
@@ -188,6 +188,12 @@ public abstract class AbstractHttpServiceRegistrar implements
GroupRegistry registry, AnnotationMetadata importingClassMetadata);
/**
* Exposes the scan for HTTP Service types, looking for
* interfaces with type or method {@link HttpExchange} annotations.
* @param basePackage the packages to look under
* @return match bean definitions
*/
protected Stream<BeanDefinition> findHttpServices(String basePackage) {
if (this.scanner == null) {
Assert.state(this.environment != null, "Environment has not been set");
@@ -257,7 +263,10 @@ public abstract class AbstractHttpServiceRegistrar implements
/**
* Detect HTTP Service types in the given packages, looking for
* interfaces with a type and/or method {@link HttpExchange} annotation.
* interfaces with type or method {@link HttpExchange} annotations.
* <p>The performed scan, however, filters out any interfaces
* annotated with {@link HttpServiceClient} that are instead supported
* by {@link HttpServiceClientRegistrarSupport}.
*/
GroupSpec detectInBasePackages(Class<?>... packageClasses);
@@ -314,11 +323,19 @@ public abstract class AbstractHttpServiceRegistrar implements
private void detectInBasePackage(String packageName) {
findHttpServices(packageName)
.filter(DefaultGroupSpec::isNotHttpServiceClientAnnotated)
.map(BeanDefinition::getBeanClassName)
.filter(Objects::nonNull)
.forEach(this::registerServiceTypeName);
}
private static boolean isNotHttpServiceClientAnnotated(BeanDefinition defintion) {
if (defintion instanceof AnnotatedBeanDefinition abd) {
return !abd.getMetadata().hasAnnotation(HttpServiceClient.class.getName());
}
return true;
}
private void registerServiceTypeName(String httpServiceTypeName) {
this.registration.httpServiceTypeNames().add(httpServiceTypeName);
}
@@ -76,10 +76,11 @@ public @interface ImportHttpServices {
String group() default HttpServiceGroup.DEFAULT_GROUP_NAME;
/**
* Detect HTTP Services in the packages of the specified classes by looking
* for interfaces with type-level or method-level
* {@link org.springframework.web.service.annotation.HttpExchange @HttpExchange}
* annotations.
* Detect HTTP Services in the packages of the specified classes, looking
* for interfaces with type or method {@link HttpExchange} annotations.
* <p>The performed scan, however, filters out interfaces annotated with
* {@link HttpServiceClient} that are instead supported by
* {@link HttpServiceClientRegistrarSupport}.
*/
Class<?>[] basePackageClasses() default {};