Add HTTP Service registrar tests
Closes gh-33992
This commit is contained in:
@@ -46,6 +46,7 @@ import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.service.annotation.HttpExchange;
|
||||
|
||||
/**
|
||||
@@ -123,12 +124,17 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
|
||||
@Override
|
||||
public final void registerBeanDefinitions(
|
||||
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry beanRegistry,
|
||||
BeanNameGenerator beanNameGenerator) {
|
||||
AnnotationMetadata metadata, BeanDefinitionRegistry registry, BeanNameGenerator generator) {
|
||||
|
||||
registerHttpServices(new DefaultGroupRegistry(), importingClassMetadata);
|
||||
registerBeanDefinitions(metadata, registry);
|
||||
}
|
||||
|
||||
String proxyRegistryBeanName = HttpServiceProxyRegistry.class.getName();
|
||||
@Override
|
||||
public final void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry beanRegistry) {
|
||||
|
||||
registerHttpServices(new DefaultGroupRegistry(), metadata);
|
||||
|
||||
String proxyRegistryBeanName = StringUtils.uncapitalize(HttpServiceProxyRegistry.class.getSimpleName());
|
||||
GenericBeanDefinition proxyRegistryBeanDef;
|
||||
|
||||
if (!beanRegistry.containsBeanDefinition(proxyRegistryBeanName)) {
|
||||
@@ -142,12 +148,12 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
proxyRegistryBeanDef = (GenericBeanDefinition) beanRegistry.getBeanDefinition(proxyRegistryBeanName);
|
||||
}
|
||||
|
||||
mergeHttpServices(proxyRegistryBeanDef);
|
||||
mergeGroups(proxyRegistryBeanDef);
|
||||
|
||||
this.groupMap.forEach((groupName, group) -> group.httpServiceTypeNames().forEach(type -> {
|
||||
GenericBeanDefinition proxyBeanDef = new GenericBeanDefinition();
|
||||
proxyBeanDef.setBeanClassName(type);
|
||||
String beanName = (groupName + "." + beanNameGenerator.generateBeanName(proxyBeanDef, beanRegistry));
|
||||
String beanName = (groupName + "#" + type);
|
||||
proxyBeanDef.setInstanceSupplier(() -> getProxyInstance(proxyRegistryBeanName, groupName, type));
|
||||
if (!beanRegistry.containsBeanDefinition(beanName)) {
|
||||
beanRegistry.registerBeanDefinition(beanName, proxyBeanDef);
|
||||
@@ -155,10 +161,6 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called before any bean definition registrations are made.
|
||||
* Subclasses must implement it to register the HTTP Services for which bean
|
||||
@@ -181,7 +183,7 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void mergeHttpServices(GenericBeanDefinition proxyRegistryBeanDef) {
|
||||
private void mergeGroups(GenericBeanDefinition proxyRegistryBeanDef) {
|
||||
ConstructorArgumentValues args = proxyRegistryBeanDef.getConstructorArgumentValues();
|
||||
ConstructorArgumentValues.ValueHolder valueHolder = args.getArgumentValue(0, Map.class);
|
||||
Assert.state(valueHolder != null, "Expected Map constructor argument at index 0");
|
||||
@@ -233,7 +235,9 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
/**
|
||||
* Perform HTTP Service registrations for the given group.
|
||||
*/
|
||||
GroupSpec forGroup(String name);
|
||||
default GroupSpec forGroup(String name) {
|
||||
return forGroup(name, HttpServiceGroup.ClientType.UNSPECIFIED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #forGroup(String)} with a client type.
|
||||
@@ -278,11 +282,6 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
*/
|
||||
private class DefaultGroupRegistry implements GroupRegistry {
|
||||
|
||||
@Override
|
||||
public GroupSpec forGroup(String name) {
|
||||
return forGroup(name, HttpServiceGroup.ClientType.UNSPECIFIED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupSpec forGroup(String name, HttpServiceGroup.ClientType clientType) {
|
||||
return new DefaultGroupSpec(name, clientType);
|
||||
@@ -313,14 +312,14 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
|
||||
@Override
|
||||
public GroupSpec register(Class<?>... serviceTypes) {
|
||||
getOrCreateGroup(groupName, clientType).addHttpServiceTypes(serviceTypes);
|
||||
getOrCreateGroup().addHttpServiceTypes(serviceTypes);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupSpec detectInBasePackages(Class<?>... packageClasses) {
|
||||
for (Class<?> packageClass : packageClasses) {
|
||||
detect(this.groupName, this.clientType, packageClass.getPackageName());
|
||||
detect(packageClass.getPackageName());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -328,21 +327,21 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
@Override
|
||||
public GroupSpec detectInBasePackages(String... packageNames) {
|
||||
for (String packageName : packageNames) {
|
||||
detect(this.groupName, this.clientType, packageName);
|
||||
detect(packageName);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void detect(String groupName, HttpServiceGroup.ClientType clientType, String packageName) {
|
||||
private void detect(String packageName) {
|
||||
for (BeanDefinition definition : getScanner().findCandidateComponents(packageName)) {
|
||||
if (definition.getBeanClassName() != null) {
|
||||
getOrCreateGroup(groupName, clientType).addHttpServiceTypeName(definition.getBeanClassName());
|
||||
getOrCreateGroup().addHttpServiceTypeName(definition.getBeanClassName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RegisteredGroup getOrCreateGroup(String groupName, HttpServiceGroup.ClientType clientType) {
|
||||
return groupMap.computeIfAbsent(groupName, name -> new RegisteredGroup(name, clientType));
|
||||
private RegisteredGroup getOrCreateGroup() {
|
||||
return groupMap.computeIfAbsent(this.groupName, name -> new RegisteredGroup(name, this.clientType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,7 +375,7 @@ public abstract class AbstractHttpServiceRegistrar implements
|
||||
|
||||
@Override
|
||||
public Set<Class<?>> httpServiceTypes() {
|
||||
return httpServiceTypeNames.stream()
|
||||
return this.httpServiceTypeNames.stream()
|
||||
.map(AbstractHttpServiceRegistrar::loadClass)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.core.type.AnnotationMetadata;
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 7.0
|
||||
*/
|
||||
final class AnnotationHttpServiceRegistrar extends AbstractHttpServiceRegistrar {
|
||||
class AnnotationHttpServiceRegistrar extends AbstractHttpServiceRegistrar {
|
||||
|
||||
@Override
|
||||
protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata importMetadata) {
|
||||
|
||||
@@ -96,10 +96,10 @@ public final class HttpServiceProxyRegistryFactoryBean
|
||||
Assert.notNull(this.applicationContext, "ApplicationContext not initialized");
|
||||
|
||||
// Apply group configurers
|
||||
this.groupSet.forEach(group ->
|
||||
this.applicationContext.getBeanProvider(group.getConfigurerType())
|
||||
.orderedStream()
|
||||
.forEach(configurer -> configurer.configureGroups(new DefaultGroups<>(group.clientType()))));
|
||||
groupAdapters.forEach((clientType, groupAdapter) ->
|
||||
this.applicationContext.getBeanProvider(groupAdapter.getConfigurerType())
|
||||
.orderedStream()
|
||||
.forEach(configurer -> configurer.configureGroups(new DefaultGroups<>(clientType))));
|
||||
|
||||
// Create proxies
|
||||
Map<String, Map<Class<?>, Object>> groupProxyMap = this.groupSet.stream()
|
||||
@@ -193,13 +193,13 @@ public final class HttpServiceProxyRegistryFactoryBean
|
||||
}
|
||||
|
||||
public Map<Class<?>, Object> createProxies() {
|
||||
Map<Class<?>, Object> proxyMap = new LinkedHashMap<>(httpServiceTypes().size());
|
||||
Map<Class<?>, Object> map = new LinkedHashMap<>(httpServiceTypes().size());
|
||||
HttpExchangeAdapter exchangeAdapter = initExchangeAdapter();
|
||||
HttpServiceProxyFactory.Builder proxyFactoryBuilder = HttpServiceProxyFactory.builderFor(exchangeAdapter);
|
||||
this.proxyFactoryConfigurer.accept(this, proxyFactoryBuilder);
|
||||
HttpServiceProxyFactory proxyFactory = proxyFactoryBuilder.build();
|
||||
httpServiceTypes().forEach(type -> proxyMap.put(type, proxyFactory.createClient(type)));
|
||||
return proxyMap;
|
||||
HttpServiceProxyFactory factory = proxyFactoryBuilder.build();
|
||||
httpServiceTypes().forEach(type -> map.put(type, factory.createClient(type)));
|
||||
return map;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -219,12 +219,10 @@ public final class HttpServiceProxyRegistryFactoryBean
|
||||
*/
|
||||
private final class DefaultGroups<CB> implements HttpServiceGroupConfigurer.Groups<CB> {
|
||||
|
||||
private final HttpServiceGroup.ClientType clientType;
|
||||
|
||||
private @Nullable Predicate<HttpServiceGroup> filter;
|
||||
private Predicate<HttpServiceGroup> filter;
|
||||
|
||||
DefaultGroups(HttpServiceGroup.ClientType clientType) {
|
||||
this.clientType = clientType;
|
||||
this.filter = group -> group.clientType().equals(clientType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -234,7 +232,7 @@ public final class HttpServiceProxyRegistryFactoryBean
|
||||
|
||||
@Override
|
||||
public HttpServiceGroupConfigurer.Groups<CB> filter(Predicate<HttpServiceGroup> predicate) {
|
||||
this.filter = (this.filter != null ? this.filter.or(predicate) : predicate);
|
||||
this.filter = this.filter.or(predicate);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -260,10 +258,8 @@ public final class HttpServiceProxyRegistryFactoryBean
|
||||
BiConsumer<HttpServiceGroup, CB> clientConfigurer,
|
||||
BiConsumer<HttpServiceGroup, HttpServiceProxyFactory.Builder> proxyFactoryConfigurer) {
|
||||
|
||||
groupSet.stream()
|
||||
.filter(group -> group.clientType().equals(this.clientType))
|
||||
.filter(groups -> this.filter == null || this.filter.test(groups))
|
||||
.forEach(group -> group.apply(clientConfigurer, proxyFactoryConfigurer));
|
||||
groupSet.stream().filter(this.filter).forEach(group ->
|
||||
group.apply(clientConfigurer, proxyFactoryConfigurer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.web.client.support.echo.EchoA;
|
||||
import org.springframework.web.client.support.echo.EchoB;
|
||||
import org.springframework.web.client.support.greeting.GreetingA;
|
||||
import org.springframework.web.client.support.greeting.GreetingB;
|
||||
import org.springframework.web.service.registry.AbstractHttpServiceRegistrar;
|
||||
import org.springframework.web.service.registry.HttpServiceProxyRegistry;
|
||||
import org.springframework.web.service.registry.ImportHttpServices;
|
||||
import org.springframework.web.service.registry.echo.EchoA;
|
||||
import org.springframework.web.service.registry.echo.EchoB;
|
||||
import org.springframework.web.service.registry.greeting.GreetingA;
|
||||
import org.springframework.web.service.registry.greeting.GreetingB;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.web.service.registry.HttpServiceGroup.ClientType;
|
||||
import org.springframework.web.service.registry.echo.EchoA;
|
||||
import org.springframework.web.service.registry.echo.EchoB;
|
||||
import org.springframework.web.service.registry.greeting.GreetingA;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AnnotationHttpServiceRegistrar}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class AnnotationHttpServiceRegistrarTests {
|
||||
|
||||
private static final String ECHO_GROUP = "echo";
|
||||
|
||||
private static final String GREETING_GROUP = "greeting";
|
||||
|
||||
|
||||
private final TestGroupRegistry groupRegistry = new TestGroupRegistry();
|
||||
|
||||
private final TestAnnotationHttpServiceRegistrar registrar = new TestAnnotationHttpServiceRegistrar();
|
||||
|
||||
|
||||
@Test
|
||||
void basicListing() {
|
||||
doRegister(ListingConfig.class);
|
||||
assertGroups(StubGroup.ofListing(ECHO_GROUP, EchoA.class, EchoB.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void basicScan() {
|
||||
doRegister(ScanConfig.class);
|
||||
assertGroups(
|
||||
StubGroup.ofPackageClasses(ECHO_GROUP, EchoA.class),
|
||||
StubGroup.ofPackageClasses(GREETING_GROUP, GreetingA.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void containerWithClientType() {
|
||||
doRegister(ContainerConfig.class);
|
||||
assertGroups(
|
||||
StubGroup.ofListing(ECHO_GROUP, ClientType.WEB_CLIENT, EchoA.class),
|
||||
StubGroup.ofListing(GREETING_GROUP, ClientType.WEB_CLIENT, GreetingA.class));
|
||||
}
|
||||
|
||||
private void doRegister(Class<?> configClass) {
|
||||
AnnotationMetadata metadata = AnnotationMetadata.introspect(configClass);
|
||||
this.registrar.registerHttpServices(this.groupRegistry, metadata);
|
||||
}
|
||||
|
||||
private void assertGroups(StubGroup... expectedGroups) {
|
||||
Map<String, StubGroup> groupMap = this.groupRegistry.groupMap();
|
||||
assertThat(groupMap.size()).isEqualTo(expectedGroups.length);
|
||||
for (StubGroup expected : expectedGroups) {
|
||||
StubGroup actual = groupMap.get(expected.name());
|
||||
assertThat(actual.httpServiceTypes()).isEqualTo(expected.httpServiceTypes());
|
||||
assertThat(actual.clientType()).isEqualTo(expected.clientType());
|
||||
assertThat(actual.packageNames()).isEqualTo(expected.packageNames());
|
||||
assertThat(actual.packageClasses()).isEqualTo(expected.packageClasses());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ImportHttpServices(group = ECHO_GROUP, types = {EchoA.class, EchoB.class})
|
||||
private static class ListingConfig {
|
||||
}
|
||||
|
||||
@ImportHttpServices(group = ECHO_GROUP, basePackageClasses = {EchoA.class})
|
||||
@ImportHttpServices(group = GREETING_GROUP, basePackageClasses = {GreetingA.class})
|
||||
private static class ScanConfig {
|
||||
}
|
||||
|
||||
@HttpServiceGroups(clientType = ClientType.WEB_CLIENT, groups = {
|
||||
@ImportHttpServices(group = ECHO_GROUP, types = {EchoA.class}),
|
||||
@ImportHttpServices(group = GREETING_GROUP, types = {GreetingA.class})
|
||||
})
|
||||
private static class ContainerConfig {
|
||||
}
|
||||
|
||||
|
||||
private static class TestAnnotationHttpServiceRegistrar extends AnnotationHttpServiceRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHttpServices(GroupRegistry registry, AnnotationMetadata importMetadata) {
|
||||
super.registerHttpServices(registry, importMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestGroupRegistry implements AbstractHttpServiceRegistrar.GroupRegistry {
|
||||
|
||||
private final Map<String, StubGroup> groupMap = new LinkedHashMap<>();
|
||||
|
||||
public Map<String, StubGroup> groupMap() {
|
||||
return this.groupMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupSpec forGroup(String name, ClientType clientType) {
|
||||
return new TestGroupSpec(name, clientType);
|
||||
}
|
||||
|
||||
private class TestGroupSpec implements GroupSpec {
|
||||
|
||||
private final String groupName;
|
||||
|
||||
private final ClientType clientType;
|
||||
|
||||
public TestGroupSpec(String groupName, ClientType clientType) {
|
||||
this.groupName = groupName;
|
||||
this.clientType = clientType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupSpec register(Class<?>... serviceTypes) {
|
||||
getOrCreateGroup().httpServiceTypes().addAll(Arrays.asList(serviceTypes));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupSpec detectInBasePackages(Class<?>... packageClasses) {
|
||||
getOrCreateGroup().packageClasses().addAll(Arrays.asList(packageClasses));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupSpec detectInBasePackages(String... packageNames) {
|
||||
getOrCreateGroup().packageNames().addAll(Arrays.asList(packageNames));
|
||||
return this;
|
||||
}
|
||||
|
||||
private StubGroup getOrCreateGroup() {
|
||||
return groupMap.computeIfAbsent(this.groupName, name -> new StubGroup(name, this.clientType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private record StubGroup(
|
||||
String name, ClientType clientType, Set<Class<?>> httpServiceTypes,
|
||||
Set<Class<?>> packageClasses, Set<String> packageNames) implements HttpServiceGroup {
|
||||
|
||||
StubGroup(String name, ClientType clientType) {
|
||||
this(name, clientType, new LinkedHashSet<>(), new LinkedHashSet<>(), new LinkedHashSet<>());
|
||||
}
|
||||
|
||||
public static StubGroup ofListing(String name, Class<?>... httpServiceTypes) {
|
||||
return ofListing(name, ClientType.UNSPECIFIED, httpServiceTypes);
|
||||
}
|
||||
|
||||
public static StubGroup ofListing(String name, ClientType clientType, Class<?>... httpServiceTypes) {
|
||||
StubGroup group = new StubGroup(name, clientType);
|
||||
group.httpServiceTypes().addAll(Arrays.asList(httpServiceTypes));
|
||||
return group;
|
||||
}
|
||||
|
||||
public static StubGroup ofPackageClasses(String name, Class<?>... packageClasses) {
|
||||
return ofPackageClasses(name, ClientType.UNSPECIFIED, packageClasses);
|
||||
}
|
||||
|
||||
public static StubGroup ofPackageClasses(String name, ClientType clientType, Class<?>... packageClasses) {
|
||||
StubGroup group = new StubGroup(name, clientType);
|
||||
group.packageClasses().addAll(Arrays.asList(packageClasses));
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* 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.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.web.service.registry.HttpServiceGroup.ClientType;
|
||||
import org.springframework.web.service.registry.echo.EchoA;
|
||||
import org.springframework.web.service.registry.echo.EchoB;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractHttpServiceRegistrar}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class HttpServiceRegistrarTests {
|
||||
|
||||
private static final String ECHO_GROUP = "echo";
|
||||
|
||||
|
||||
private final SimpleBeanDefinitionRegistry beanDefRegistry = new SimpleBeanDefinitionRegistry();
|
||||
|
||||
|
||||
@Test
|
||||
void basicListing() {
|
||||
doRegister(registry -> registry.forGroup(ECHO_GROUP).register(EchoA.class, EchoB.class));
|
||||
|
||||
assertRegistryBeanDef(new TestGroup(ECHO_GROUP, EchoA.class, EchoB.class));
|
||||
assertProxyBeanDef(ECHO_GROUP, EchoA.class);
|
||||
assertProxyBeanDef(ECHO_GROUP, EchoB.class);
|
||||
assertBeanDefinitionCount(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void basicScan() {
|
||||
doRegister(registry -> registry.forGroup(ECHO_GROUP).detectInBasePackages(EchoA.class));
|
||||
|
||||
assertRegistryBeanDef(new TestGroup(ECHO_GROUP, EchoA.class, EchoB.class));
|
||||
assertProxyBeanDef(ECHO_GROUP, EchoA.class);
|
||||
assertProxyBeanDef(ECHO_GROUP, EchoB.class);
|
||||
assertBeanDefinitionCount(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void merge() {
|
||||
doRegister(
|
||||
registry -> registry.forGroup(ECHO_GROUP).register(EchoA.class),
|
||||
registry -> registry.forGroup(ECHO_GROUP).register(EchoB.class));
|
||||
|
||||
assertRegistryBeanDef(new TestGroup(ECHO_GROUP, EchoA.class, EchoB.class));
|
||||
assertProxyBeanDef(ECHO_GROUP, EchoA.class);
|
||||
assertProxyBeanDef(ECHO_GROUP, EchoB.class);
|
||||
assertBeanDefinitionCount(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mergeWithOverlap() {
|
||||
doRegister(
|
||||
registry -> registry.forGroup(ECHO_GROUP).register(EchoA.class),
|
||||
registry -> registry.forGroup(ECHO_GROUP).register(EchoA.class));
|
||||
|
||||
assertRegistryBeanDef(new TestGroup(ECHO_GROUP, EchoA.class));
|
||||
assertProxyBeanDef(ECHO_GROUP, EchoA.class);
|
||||
assertBeanDefinitionCount(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mergeWithClientTypeConflict() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> doRegister(
|
||||
registry -> registry.forGroup(ECHO_GROUP, ClientType.REST_CLIENT).register(EchoA.class),
|
||||
registry -> registry.forGroup(ECHO_GROUP, ClientType.WEB_CLIENT).register(EchoB.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultClientType() {
|
||||
doRegister(ClientType.WEB_CLIENT, registry -> registry.forGroup(ECHO_GROUP).register(EchoA.class));
|
||||
assertRegistryBeanDef(new TestGroup(ECHO_GROUP, ClientType.WEB_CLIENT, EchoA.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void noRegistrations() {
|
||||
doRegister(registry -> {});
|
||||
assertRegistryBeanDef();
|
||||
assertBeanDefinitionCount(1);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void doRegister(Consumer<AbstractHttpServiceRegistrar.GroupRegistry>... registrars) {
|
||||
doRegister(ClientType.UNSPECIFIED, registrars);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
private void doRegister(ClientType clientType, Consumer<AbstractHttpServiceRegistrar.GroupRegistry>... consumers) {
|
||||
for (Consumer<AbstractHttpServiceRegistrar.GroupRegistry> consumer : consumers) {
|
||||
TestRegistrar registrar = new TestRegistrar(consumer, clientType);
|
||||
registrar.registerBeanDefinitions(null, beanDefRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertRegistryBeanDef(HttpServiceGroup... expectedGroups) {
|
||||
Map<String, HttpServiceGroup> groupMap = groupMap();
|
||||
assertThat(groupMap.size()).isEqualTo(expectedGroups.length);
|
||||
for (HttpServiceGroup expected : expectedGroups) {
|
||||
HttpServiceGroup actual = groupMap.get(expected.name());
|
||||
assertThat(actual.httpServiceTypes()).isEqualTo(expected.httpServiceTypes());
|
||||
assertThat(actual.clientType()).isEqualTo(expected.clientType());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, HttpServiceGroup> groupMap() {
|
||||
BeanDefinition beanDef = this.beanDefRegistry.getBeanDefinition("httpServiceProxyRegistry");
|
||||
assertThat(beanDef.getBeanClassName()).isEqualTo(HttpServiceProxyRegistryFactoryBean.class.getName());
|
||||
|
||||
ConstructorArgumentValues args = beanDef.getConstructorArgumentValues();
|
||||
ConstructorArgumentValues.ValueHolder valueHolder = args.getArgumentValue(0, Map.class);
|
||||
assertThat(valueHolder).isNotNull();
|
||||
|
||||
Map<String, HttpServiceGroup> groupMap = (Map<String, HttpServiceGroup>) valueHolder.getValue();
|
||||
assertThat(groupMap).isNotNull();
|
||||
|
||||
return groupMap;
|
||||
}
|
||||
|
||||
private void assertProxyBeanDef(String group, Class<?> httpServiceType) {
|
||||
String beanName = group + "#" + httpServiceType.getName();
|
||||
assertThat(this.beanDefRegistry.containsBeanDefinition(beanName)).isTrue();
|
||||
BeanDefinition beanDef = this.beanDefRegistry.getBeanDefinition(beanName);
|
||||
assertThat(beanDef.getBeanClassName()).isEqualTo(httpServiceType.getName());
|
||||
|
||||
}
|
||||
|
||||
private void assertBeanDefinitionCount(int count) {
|
||||
assertThat(beanDefRegistry.getBeanDefinitionCount()).isEqualTo(count);
|
||||
}
|
||||
|
||||
|
||||
private static class TestRegistrar extends AbstractHttpServiceRegistrar {
|
||||
|
||||
private final Consumer<GroupRegistry> registrar;
|
||||
|
||||
TestRegistrar(Consumer<GroupRegistry> registrar, ClientType clientType) {
|
||||
this.registrar = registrar;
|
||||
setDefaultClientType(clientType);
|
||||
setEnvironment(new StandardEnvironment());
|
||||
setResourceLoader(new PathMatchingResourcePatternResolver());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata metadata) {
|
||||
this.registrar.accept(registry);
|
||||
}
|
||||
}
|
||||
|
||||
private record TestGroup(String name, Set<Class<?>> httpServiceTypes, ClientType clientType)
|
||||
implements HttpServiceGroup {
|
||||
|
||||
TestGroup(String name, Class<?>... httpServiceTypes) {
|
||||
this(name, Set.of(httpServiceTypes), ClientType.REST_CLIENT);
|
||||
}
|
||||
|
||||
TestGroup(String name, ClientType clientType, Class<?>... httpServiceTypes) {
|
||||
this(name, Set.of(httpServiceTypes), clientType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.client.support.echo;
|
||||
package org.springframework.web.service.registry.echo;
|
||||
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.client.support.echo;
|
||||
package org.springframework.web.service.registry.echo;
|
||||
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.client.support.greeting;
|
||||
package org.springframework.web.service.registry.greeting;
|
||||
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.client.support.greeting;
|
||||
package org.springframework.web.service.registry.greeting;
|
||||
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
Reference in New Issue
Block a user