diff --git a/spring-web/src/main/java/org/springframework/web/service/registry/AnnotationHttpServiceRegistrar.java b/spring-web/src/main/java/org/springframework/web/service/registry/AnnotationHttpServiceRegistrar.java index 72635aa974..f89d831d68 100644 --- a/spring-web/src/main/java/org/springframework/web/service/registry/AnnotationHttpServiceRegistrar.java +++ b/spring-web/src/main/java/org/springframework/web/service/registry/AnnotationHttpServiceRegistrar.java @@ -32,28 +32,23 @@ import org.springframework.core.type.AnnotationMetadata; class AnnotationHttpServiceRegistrar extends AbstractHttpServiceRegistrar { @Override - protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata importMetadata) { + protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata metadata) { - MergedAnnotation groupsAnnot = importMetadata.getAnnotations().get(ImportHttpServiceGroups.class); + MergedAnnotation groupsAnnot = metadata.getAnnotations().get(ImportHttpServices.Container.class); if (groupsAnnot.isPresent()) { - HttpServiceGroup.ClientType clientType = groupsAnnot.getEnum("clientType", HttpServiceGroup.ClientType.class); for (MergedAnnotation annot : groupsAnnot.getAnnotationArray("value", ImportHttpServices.class)) { - processImportAnnotation(annot, registry, clientType); + processImportAnnotation(annot, registry); } } - importMetadata.getAnnotations().stream(ImportHttpServices.class).forEach(annot -> - processImportAnnotation(annot, registry, HttpServiceGroup.ClientType.UNSPECIFIED)); + metadata.getAnnotations().stream(ImportHttpServices.class) + .forEach(annot -> processImportAnnotation(annot, registry)); } - private void processImportAnnotation( - MergedAnnotation annotation, GroupRegistry groupRegistry, - HttpServiceGroup.ClientType containerClientType) { + private void processImportAnnotation(MergedAnnotation annotation, GroupRegistry groupRegistry) { String groupName = annotation.getString("group"); - HttpServiceGroup.ClientType clientType = annotation.getEnum("clientType", HttpServiceGroup.ClientType.class); - clientType = (clientType != HttpServiceGroup.ClientType.UNSPECIFIED ? clientType : containerClientType); groupRegistry.forGroup(groupName, clientType) .register(annotation.getClassArray("types")) diff --git a/spring-web/src/main/java/org/springframework/web/service/registry/HttpServiceGroup.java b/spring-web/src/main/java/org/springframework/web/service/registry/HttpServiceGroup.java index 858197023b..3a57e6e193 100644 --- a/spring-web/src/main/java/org/springframework/web/service/registry/HttpServiceGroup.java +++ b/spring-web/src/main/java/org/springframework/web/service/registry/HttpServiceGroup.java @@ -70,7 +70,6 @@ public interface HttpServiceGroup { /** * Not specified, falling back on a default. * @see ImportHttpServices#clientType() - * @see ImportHttpServiceGroups#clientType() * @see AbstractHttpServiceRegistrar#setDefaultClientType */ UNSPECIFIED; diff --git a/spring-web/src/main/java/org/springframework/web/service/registry/ImportHttpServiceGroups.java b/spring-web/src/main/java/org/springframework/web/service/registry/ImportHttpServiceGroups.java deleted file mode 100644 index d8cabb86fd..0000000000 --- a/spring-web/src/main/java/org/springframework/web/service/registry/ImportHttpServiceGroups.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2002-2025 the original author or authors. - * - * 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 - * - * https://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 org.springframework.web.service.registry; - -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; - -import org.springframework.context.annotation.Import; -import org.springframework.core.annotation.AliasFor; - -/** - * Container annotation for the {@link ImportHttpServices} repeatable annotation. - * Typically not necessary to use as {@code @ImportHttpServices} annotations can - * be declared one after another without a wrapper, but the container annotation - * may be used to set the {@link #clientType()} and that would be inherited by - * all nested annotations. - * - * @author Olga Maciaszek-Sharma - * @author Rossen Stoyanchev - * @since 7.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Import(AnnotationHttpServiceRegistrar.class) -public @interface ImportHttpServiceGroups { - - /** - * Alias for {@link #groups()}. - */ - @AliasFor("groups") - ImportHttpServices[] value() default {}; - - /** - * Nested annotations that declare HTTP Services by group. - */ - @AliasFor("value") - ImportHttpServices[] groups() default {}; - - /** - * Specify the type of client to use for nested {@link ImportHttpServices} - * annotations that don't specify it. - *

By default, this is {@link HttpServiceGroup.ClientType#UNSPECIFIED} - * in which case {@code RestClient} is used, but this default can be reset - * via {@link AbstractHttpServiceRegistrar#setDefaultClientType}. - */ - HttpServiceGroup.ClientType clientType() default HttpServiceGroup.ClientType.UNSPECIFIED; - -} diff --git a/spring-web/src/main/java/org/springframework/web/service/registry/ImportHttpServices.java b/spring-web/src/main/java/org/springframework/web/service/registry/ImportHttpServices.java index 5e656a2a37..9bd5e94e0c 100644 --- a/spring-web/src/main/java/org/springframework/web/service/registry/ImportHttpServices.java +++ b/spring-web/src/main/java/org/springframework/web/service/registry/ImportHttpServices.java @@ -46,12 +46,12 @@ import org.springframework.web.service.annotation.HttpExchange; * @author Olga Maciaszek-Sharma * @author Rossen Stoyanchev * @since 7.0 - * @see ImportHttpServiceGroups + * @see Container * @see AbstractHttpServiceRegistrar */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) -@Repeatable(ImportHttpServiceGroups.class) +@Repeatable(ImportHttpServices.Container.class) @Import(AnnotationHttpServiceRegistrar.class) @Documented public @interface ImportHttpServices { @@ -96,4 +96,19 @@ public @interface ImportHttpServices { */ HttpServiceGroup.ClientType clientType() default HttpServiceGroup.ClientType.UNSPECIFIED; + + /** + * Container annotation that is necessary for the repeatable + * {@link ImportHttpServices} annotation, but does not need to be declared + * in application code. + */ + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + @Documented + @Import(AnnotationHttpServiceRegistrar.class) + @interface Container { + + ImportHttpServices[] value() default {}; + } + } diff --git a/spring-web/src/test/java/org/springframework/web/service/registry/AnnotationHttpServiceRegistrarTests.java b/spring-web/src/test/java/org/springframework/web/service/registry/AnnotationHttpServiceRegistrarTests.java index 4be7150c74..fa2663e060 100644 --- a/spring-web/src/test/java/org/springframework/web/service/registry/AnnotationHttpServiceRegistrarTests.java +++ b/spring-web/src/test/java/org/springframework/web/service/registry/AnnotationHttpServiceRegistrarTests.java @@ -63,8 +63,8 @@ public class AnnotationHttpServiceRegistrarTests { } @Test - void containerWithClientType() { - doRegister(ContainerConfig.class); + void clientType() { + doRegister(ClientTypeConfig.class); assertGroups( StubGroup.ofListing(ECHO_GROUP, ClientType.WEB_CLIENT, EchoA.class), StubGroup.ofListing(GREETING_GROUP, ClientType.WEB_CLIENT, GreetingA.class)); @@ -97,19 +97,17 @@ public class AnnotationHttpServiceRegistrarTests { private static class ScanConfig { } - @ImportHttpServiceGroups(clientType = ClientType.WEB_CLIENT, groups = { - @ImportHttpServices(group = ECHO_GROUP, types = {EchoA.class}), - @ImportHttpServices(group = GREETING_GROUP, types = {GreetingA.class}) - }) - private static class ContainerConfig { + @ImportHttpServices(clientType = ClientType.WEB_CLIENT, group = ECHO_GROUP, types = {EchoA.class}) + @ImportHttpServices(clientType = ClientType.WEB_CLIENT, group = GREETING_GROUP, types = {GreetingA.class}) + private static class ClientTypeConfig { } private static class TestAnnotationHttpServiceRegistrar extends AnnotationHttpServiceRegistrar { @Override - public void registerHttpServices(GroupRegistry registry, AnnotationMetadata importMetadata) { - super.registerHttpServices(registry, importMetadata); + public void registerHttpServices(GroupRegistry registry, AnnotationMetadata metadata) { + super.registerHttpServices(registry, metadata); } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/support/WebClientProxyRegistryIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/support/WebClientProxyRegistryIntegrationTests.java index ff1a4f3be0..0c2beacb3f 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/support/WebClientProxyRegistryIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/support/WebClientProxyRegistryIntegrationTests.java @@ -37,9 +37,8 @@ import org.springframework.web.reactive.function.client.support.greeting.Greetin import org.springframework.web.reactive.function.client.support.greeting.GreetingB; import org.springframework.web.service.registry.AbstractHttpServiceRegistrar; import org.springframework.web.service.registry.HttpServiceGroup.ClientType; -import org.springframework.web.service.registry.ImportHttpServices; -import org.springframework.web.service.registry.ImportHttpServiceGroups; import org.springframework.web.service.registry.HttpServiceProxyRegistry; +import org.springframework.web.service.registry.ImportHttpServices; import static org.assertj.core.api.Assertions.assertThat; @@ -126,19 +125,15 @@ public class WebClientProxyRegistryIntegrationTests { @Configuration(proxyBeanMethods = false) - @ImportHttpServiceGroups(clientType = ClientType.WEB_CLIENT, groups = { - @ImportHttpServices(group = "echo", types = {EchoA.class, EchoB.class}), - @ImportHttpServices(group = "greeting", types = {GreetingA.class, GreetingB.class}) - }) + @ImportHttpServices(clientType = ClientType.WEB_CLIENT, group = "echo", types = {EchoA.class, EchoB.class}) + @ImportHttpServices(clientType = ClientType.WEB_CLIENT, group = "greeting", types = {GreetingA.class, GreetingB.class}) private static class ListingConfig extends BaseEchoConfig { } @Configuration(proxyBeanMethods = false) - @ImportHttpServiceGroups(clientType = ClientType.WEB_CLIENT, groups = { - @ImportHttpServices(group = "echo", basePackageClasses = EchoA.class), - @ImportHttpServices(group = "greeting", basePackageClasses = GreetingA.class) - }) + @ImportHttpServices(clientType = ClientType.WEB_CLIENT, group = "echo", basePackageClasses = EchoA.class) + @ImportHttpServices(clientType = ClientType.WEB_CLIENT, group = "greeting", basePackageClasses = GreetingA.class) private static class DetectConfig extends BaseEchoConfig { }