Make container annotation for ImportHttpServices nested
See gh-33992
This commit is contained in:
@@ -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"))
|
||||
|
||||
@@ -70,7 +70,6 @@ public interface HttpServiceGroup {
|
||||
/**
|
||||
* Not specified, falling back on a default.
|
||||
* @see ImportHttpServices#clientType()
|
||||
* @see ImportHttpServiceGroups#clientType()
|
||||
* @see AbstractHttpServiceRegistrar#setDefaultClientType
|
||||
*/
|
||||
UNSPECIFIED;
|
||||
|
||||
@@ -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.
|
||||
* <p>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;
|
||||
|
||||
}
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user