From 1e8c957ab024e3e6e6c528057cde011407b4c871 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 10:14:50 +0800 Subject: [PATCH 01/19] Add DiscoveryUtils and enhance service registry support Introduced DiscoveryUtils for utility methods related to discovery properties and conversions between SimpleDiscoveryProperties and SimpleReactiveDiscoveryProperties. Updated SimpleServiceRegistry to support both property types and refactored constructors. Added new constants for reactive auto-configuration classes and extended related tests to cover new utilities and constructors. --- ...ctiveDiscoveryClientAutoConfiguration.java | 7 ++ .../constants/DiscoveryClientConstants.java | 16 +++ .../client/discovery/util/DiscoveryUtils.java | 100 ++++++++++++++++++ .../registry/SimpleServiceRegistry.java | 18 +++- .../service/util/ServiceInstanceUtils.java | 17 +++ .../DiscoveryClientConstantsTest.java | 4 + .../discovery/util/DiscoveryUtilsTest.java | 85 +++++++++++++++ .../registry/SimpleServiceRegistryTest.java | 15 ++- 8 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java create mode 100644 microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtilsTest.java diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/autoconfigure/ReactiveDiscoveryClientAutoConfiguration.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/autoconfigure/ReactiveDiscoveryClientAutoConfiguration.java index ec164f2..26aa7b1 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/autoconfigure/ReactiveDiscoveryClientAutoConfiguration.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/autoconfigure/ReactiveDiscoveryClientAutoConfiguration.java @@ -18,6 +18,7 @@ package io.microsphere.spring.cloud.client.discovery.autoconfigure; import io.microsphere.spring.cloud.client.discovery.ReactiveDiscoveryClientAdapter; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -30,6 +31,8 @@ import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.DISCOVERY_CLIENT_CLASS_NAME; import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.REACTIVE_COMMONS_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; +import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.REACTIVE_COMPOSITE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; +import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.SIMPLE_REACTIVE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; /** * The Auto-Configuration class for {@link ReactiveDiscoveryClient} @@ -48,6 +51,10 @@ @AutoConfigureBefore(name = { REACTIVE_COMMONS_CLIENT_AUTO_CONFIGURATION_CLASS_NAME }) +@AutoConfigureAfter(name = { + SIMPLE_REACTIVE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME, + REACTIVE_COMPOSITE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME +}) public class ReactiveDiscoveryClientAutoConfiguration { @Configuration(proxyBeanMethods = false) diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/constants/DiscoveryClientConstants.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/constants/DiscoveryClientConstants.java index 505c5a9..5cce42f 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/constants/DiscoveryClientConstants.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/constants/DiscoveryClientConstants.java @@ -20,6 +20,8 @@ import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient; +import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration; +import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration; /** * The constants for {@link DiscoveryClient} @@ -56,4 +58,18 @@ public interface DiscoveryClientConstants { * @see org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration */ String REACTIVE_COMMONS_CLIENT_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration"; + + /** + * The class name of {@link SimpleReactiveDiscoveryClientAutoConfiguration} + * + * @see org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration + */ + String SIMPLE_REACTIVE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration"; + + /** + * The class name of {@link ReactiveCompositeDiscoveryClientAutoConfiguration} + * + * @see org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration + */ + String REACTIVE_COMPOSITE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration"; } \ No newline at end of file diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java new file mode 100644 index 0000000..dc1dd9f --- /dev/null +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 io.microsphere.spring.cloud.client.discovery.util; + +import io.microsphere.annotation.Nonnull; +import io.microsphere.util.Utils; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties; +import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryProperties; + +import java.util.List; +import java.util.Map; + +import static io.microsphere.reflect.MethodUtils.invokeMethod; + +/** + * The utilities class for Spring Cloud Discovery + * + * @author Mercy + * @see Utils + * @since 1.0.0 + */ +public abstract class DiscoveryUtils implements Utils { + + /** + * Get the instances map from {@link SimpleDiscoveryProperties} + * + * @param properties {@link SimpleDiscoveryProperties} + * @return the instances map + */ + @Nonnull + public static Map> getInstancesMap(SimpleDiscoveryProperties properties) { + return properties.getInstances(); + } + + /** + * Get the instances map from {@link SimpleReactiveDiscoveryProperties} + * + * @param properties {@link SimpleReactiveDiscoveryProperties} + * @return the instances map + */ + @Nonnull + public static Map> getInstancesMap(SimpleReactiveDiscoveryProperties properties) { + return invokeMethod(properties, "getInstances"); + } + + public static SimpleReactiveDiscoveryProperties simpleReactiveDiscoveryProperties(@Nonnull SimpleDiscoveryProperties properties) { + SimpleReactiveDiscoveryProperties simpleReactiveDiscoveryProperties = new SimpleReactiveDiscoveryProperties(); + simpleReactiveDiscoveryProperties.setOrder(properties.getOrder()); + + DefaultServiceInstance local = properties.getLocal(); + DefaultServiceInstance targetLocal = simpleReactiveDiscoveryProperties.getLocal(); + + simpleReactiveDiscoveryProperties.setInstances(getInstancesMap(properties)); + + simpleReactiveDiscoveryProperties.afterPropertiesSet(); + + return simpleReactiveDiscoveryProperties; + } + + /** + * Convert {@link SimpleReactiveDiscoveryProperties} to {@link SimpleDiscoveryProperties} + * + * @param properties {@link SimpleReactiveDiscoveryProperties} + * @return {@link SimpleDiscoveryProperties} + */ + @Nonnull + public static SimpleDiscoveryProperties simpleDiscoveryProperties(@Nonnull SimpleReactiveDiscoveryProperties properties) { + SimpleDiscoveryProperties simpleDiscoveryProperties = new SimpleDiscoveryProperties(); + simpleDiscoveryProperties.setOrder(properties.getOrder()); + + DefaultServiceInstance local = properties.getLocal(); + simpleDiscoveryProperties.setInstance(local.getServiceId(), local.getHost(), local.getPort()); + + Map> instances = invokeMethod(properties, "getInstances"); + simpleDiscoveryProperties.setInstances(instances); + + simpleDiscoveryProperties.afterPropertiesSet(); + + return simpleDiscoveryProperties; + } + + private DiscoveryUtils() { + } +} diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/registry/SimpleServiceRegistry.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/registry/SimpleServiceRegistry.java index 262a4e0..6d90e12 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/registry/SimpleServiceRegistry.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/registry/SimpleServiceRegistry.java @@ -19,23 +19,27 @@ import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties; +import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryProperties; import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import java.util.ArrayList; import java.util.List; import java.util.Map; +import static io.microsphere.spring.cloud.client.discovery.util.DiscoveryUtils.getInstancesMap; import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtils.getMetadata; import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtils.setMetadata; /** - * Simple {@link ServiceRegistry} class that is based on {@link SimpleDiscoveryProperties} to register + * Simple {@link ServiceRegistry} class that is based on {@link SimpleDiscoveryProperties} + * or {@link SimpleReactiveDiscoveryProperties} to register * {@link DefaultRegistration}. * * @author Mercy * @see ServiceRegistry * @see DefaultRegistration * @see SimpleDiscoveryProperties#getInstances() + * @see SimpleReactiveDiscoveryProperties#getInstances() * @since 1.0.0 */ public class SimpleServiceRegistry implements ServiceRegistry { @@ -44,8 +48,16 @@ public class SimpleServiceRegistry implements ServiceRegistry> instancesMap; - public SimpleServiceRegistry(SimpleDiscoveryProperties simpleDiscoveryProperties) { - this.instancesMap = simpleDiscoveryProperties.getInstances(); + public SimpleServiceRegistry(SimpleDiscoveryProperties properties) { + this(getInstancesMap(properties)); + } + + public SimpleServiceRegistry(SimpleReactiveDiscoveryProperties properties) { + this(getInstancesMap(properties)); + } + + public SimpleServiceRegistry(Map> instancesMap) { + this.instancesMap = instancesMap; } @Override diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java index 2a45429..39143d4 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java @@ -162,6 +162,23 @@ public static String removeMetadata(ServiceInstance serviceInstance, String meta return metadata.remove(metadataName); } + /** + * Set properties from source to target + * + * @param source source {@link ServiceInstance} + * @param target target {@link DefaultServiceInstance} + */ + public static void setProperties(ServiceInstance source, DefaultServiceInstance target) { + target.setInstanceId(source.getInstanceId()); + target.setServiceId(source.getServiceId()); + target.setHost(source.getHost()); + target.setPort(source.getPort()); + target.setSecure(source.isSecure()); + Map metadata = source.getMetadata(); + metadata.clear(); + metadata.putAll(source.getMetadata()); + } + static List parseWebEndpointMappings(String encodedJSON) { if (isBlank(encodedJSON)) { return emptyList(); diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/constants/DiscoveryClientConstantsTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/constants/DiscoveryClientConstantsTest.java index b92ae18..131a2c1 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/constants/DiscoveryClientConstantsTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/constants/DiscoveryClientConstantsTest.java @@ -22,6 +22,8 @@ import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.COMPOSITE_DISCOVERY_CLIENT_CLASS_NAME; import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.DISCOVERY_CLIENT_CLASS_NAME; import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.REACTIVE_COMMONS_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; +import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.REACTIVE_COMPOSITE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; +import static io.microsphere.spring.cloud.client.discovery.constants.DiscoveryClientConstants.SIMPLE_REACTIVE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -39,5 +41,7 @@ void testConstants() { assertEquals("org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient", COMPOSITE_DISCOVERY_CLIENT_CLASS_NAME); assertEquals("org.springframework.cloud.client.CommonsClientAutoConfiguration", COMMONS_CLIENT_AUTO_CONFIGURATION_CLASS_NAME); assertEquals("org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration", REACTIVE_COMMONS_CLIENT_AUTO_CONFIGURATION_CLASS_NAME); + assertEquals("org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration", SIMPLE_REACTIVE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME); + assertEquals("org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration", REACTIVE_COMPOSITE_DISCOVERY_CLIENT_AUTO_CONFIGURATION_CLASS_NAME); } } \ No newline at end of file diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtilsTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtilsTest.java new file mode 100644 index 0000000..c795655 --- /dev/null +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtilsTest.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 io.microsphere.spring.cloud.client.discovery.util; + + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties; +import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryProperties; + +import java.util.List; +import java.util.Map; + +import static io.microsphere.collection.Lists.ofList; +import static io.microsphere.spring.cloud.client.discovery.util.DiscoveryUtils.getInstancesMap; +import static io.microsphere.spring.cloud.client.discovery.util.DiscoveryUtils.simpleDiscoveryProperties; +import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtilsTest.createDefaultServiceInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * {@link DiscoveryUtils} Test + * + * @author Mercy + * @see DiscoveryUtils + * @since 1.0.0 + */ +class DiscoveryUtilsTest { + + private DefaultServiceInstance serviceInstance; + + private SimpleDiscoveryProperties properties; + + @BeforeEach + void setUp() { + this.serviceInstance = createDefaultServiceInstance(); + this.properties = new SimpleDiscoveryProperties(); + Map> instancesMap = this.properties.getInstances(); + instancesMap.put(this.serviceInstance.getInstanceId(), ofList(this.serviceInstance)); + } + + @Test + void testGetInstancesMap() { + Map> instancesMap = getInstancesMap(this.properties); + assertEquals(1, instancesMap.size()); + assertEquals(ofList(this.serviceInstance), instancesMap.get(this.serviceInstance.getInstanceId())); + } + + @Test + void testGetInstancesMapFromSimpleReactiveDiscoveryProperties() { + SimpleReactiveDiscoveryProperties properties = new SimpleReactiveDiscoveryProperties(); + Map> instancesMap = getInstancesMap(properties); + assertTrue(instancesMap.isEmpty()); + + properties.setInstances(this.properties.getInstances()); + instancesMap = getInstancesMap(properties); + assertEquals(1, instancesMap.size()); + assertEquals(ofList(this.serviceInstance), instancesMap.get(this.serviceInstance.getInstanceId())); + } + + @Test + void testSimpleDiscoveryProperties() { + SimpleReactiveDiscoveryProperties properties = new SimpleReactiveDiscoveryProperties(); + properties.setInstances(this.properties.getInstances()); + + SimpleDiscoveryProperties simpleDiscoveryProperties = simpleDiscoveryProperties(properties); + assertEquals(this.properties.getInstances(), simpleDiscoveryProperties.getInstances()); + } +} \ No newline at end of file diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/registry/SimpleServiceRegistryTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/registry/SimpleServiceRegistryTest.java index 028a878..1b11e19 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/registry/SimpleServiceRegistryTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/registry/SimpleServiceRegistryTest.java @@ -22,10 +22,12 @@ import org.junit.jupiter.api.Test; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties; +import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryProperties; import java.util.List; import java.util.Map; +import static io.microsphere.spring.cloud.client.discovery.util.DiscoveryUtils.simpleReactiveDiscoveryProperties; import static io.microsphere.spring.cloud.client.service.registry.DefaultRegistrationTest.createDefaultRegistration; import static io.microsphere.spring.cloud.client.service.registry.SimpleServiceRegistry.STATUS_KEY; import static java.util.Collections.emptyList; @@ -55,6 +57,13 @@ void setUp() { this.registry = new SimpleServiceRegistry(this.properties); } + @Test + void testConstructor() { + SimpleReactiveDiscoveryProperties properties = simpleReactiveDiscoveryProperties(this.properties); + this.registry = new SimpleServiceRegistry(properties); + testDeregister(); + } + @Test void testRegister() { Map> instancesMap = this.properties.getInstances(); @@ -94,10 +103,8 @@ void testSetStatus() { @Test void testGetStatus() { - testRegister(); - String status = "UP"; - this.registry.setStatus(this.registration, status); - assertEquals(status, this.registry.getStatus(this.registration)); + testSetStatus(); + assertEquals(this.registration.getMetadata().get(STATUS_KEY), this.registry.getStatus(this.registration)); } List getInstances(String serviceId) { From 4999be23faf5ba9772178943bc24fd60472ab358 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 10:25:26 +0800 Subject: [PATCH 02/19] Refactor setProperties to use URI and update tests Updated ServiceInstanceUtils.setProperties to set the URI on the target DefaultServiceInstance instead of host, port, and secure fields. Adjusted DiscoveryUtils to use the new setProperties method and updated the related test to verify the new behavior. --- .../cloud/client/discovery/util/DiscoveryUtils.java | 9 ++++----- .../cloud/client/service/util/ServiceInstanceUtils.java | 5 ++--- .../client/service/util/ServiceInstanceUtilsTest.java | 8 ++++++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java index dc1dd9f..633d940 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java @@ -27,6 +27,7 @@ import java.util.Map; import static io.microsphere.reflect.MethodUtils.invokeMethod; +import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtils.setProperties; /** * The utilities class for Spring Cloud Discovery @@ -65,10 +66,10 @@ public static SimpleReactiveDiscoveryProperties simpleReactiveDiscoveryPropertie DefaultServiceInstance local = properties.getLocal(); DefaultServiceInstance targetLocal = simpleReactiveDiscoveryProperties.getLocal(); + setProperties(targetLocal, local); - simpleReactiveDiscoveryProperties.setInstances(getInstancesMap(properties)); - - simpleReactiveDiscoveryProperties.afterPropertiesSet(); + Map> instances = getInstancesMap(properties); + simpleReactiveDiscoveryProperties.setInstances(instances); return simpleReactiveDiscoveryProperties; } @@ -90,8 +91,6 @@ public static SimpleDiscoveryProperties simpleDiscoveryProperties(@Nonnull Simpl Map> instances = invokeMethod(properties, "getInstances"); simpleDiscoveryProperties.setInstances(instances); - simpleDiscoveryProperties.afterPropertiesSet(); - return simpleDiscoveryProperties; } diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java index 39143d4..3cc7db4 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java @@ -171,9 +171,8 @@ public static String removeMetadata(ServiceInstance serviceInstance, String meta public static void setProperties(ServiceInstance source, DefaultServiceInstance target) { target.setInstanceId(source.getInstanceId()); target.setServiceId(source.getServiceId()); - target.setHost(source.getHost()); - target.setPort(source.getPort()); - target.setSecure(source.isSecure()); + URI uri = getUri(source); + target.setUri(uri); Map metadata = source.getMetadata(); metadata.clear(); metadata.putAll(source.getMetadata()); diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtilsTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtilsTest.java index 5f62d98..18ef90c 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtilsTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtilsTest.java @@ -39,6 +39,7 @@ import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtils.parseWebEndpointMappings; import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtils.removeMetadata; import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtils.setMetadata; +import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtils.setProperties; import static io.microsphere.spring.web.metadata.WebEndpointMapping.Kind.SERVLET; import static io.microsphere.spring.web.metadata.WebEndpointMapping.servlet; import static io.microsphere.util.StringUtils.EMPTY_STRING; @@ -144,6 +145,13 @@ void testMetadataOps() { assertNull(getMetadata(this.serviceInstance, WEB_CONTEXT_PATH_METADATA_NAME)); } + @Test + void testSetProperties() { + DefaultServiceInstance target = new DefaultServiceInstance(); + setProperties(this.serviceInstance, target); + assertEquals(this.serviceInstance, target); + } + private Collection createWebEndpointMappings() { return ofList(buildWebEndpointMapping(true)); } From 8b3429ea268148210fc97728cc4e8062c1b1c265 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 10:26:59 +0800 Subject: [PATCH 03/19] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9a2c4e2..7d496b1 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,7 @@ - 0.1.3-SNAPSHOT + 0.1.4-SNAPSHOT From 393fe17548d9d5aae3ebfff677debfb7f7dc2464 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 10:31:22 +0800 Subject: [PATCH 04/19] Add @Nonnull annotations to DiscoveryUtils methods Added @Nonnull annotations to method parameters in DiscoveryUtils to improve null-safety and clarify API contracts. Also updated method signatures for better consistency. --- .../cloud/client/discovery/util/DiscoveryUtils.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java index 633d940..db3a521 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/util/DiscoveryUtils.java @@ -45,7 +45,7 @@ public abstract class DiscoveryUtils implements Utils { * @return the instances map */ @Nonnull - public static Map> getInstancesMap(SimpleDiscoveryProperties properties) { + public static Map> getInstancesMap(@Nonnull SimpleDiscoveryProperties properties) { return properties.getInstances(); } @@ -56,10 +56,17 @@ public static Map> getInstancesMap(SimpleDi * @return the instances map */ @Nonnull - public static Map> getInstancesMap(SimpleReactiveDiscoveryProperties properties) { + public static Map> getInstancesMap(@Nonnull SimpleReactiveDiscoveryProperties properties) { return invokeMethod(properties, "getInstances"); } + /** + * Convert {@link SimpleDiscoveryProperties} to {@link SimpleReactiveDiscoveryProperties} + * + * @param properties {@link SimpleDiscoveryProperties} + * @return {@link SimpleReactiveDiscoveryProperties} + */ + @Nonnull public static SimpleReactiveDiscoveryProperties simpleReactiveDiscoveryProperties(@Nonnull SimpleDiscoveryProperties properties) { SimpleReactiveDiscoveryProperties simpleReactiveDiscoveryProperties = new SimpleReactiveDiscoveryProperties(); simpleReactiveDiscoveryProperties.setOrder(properties.getOrder()); @@ -96,4 +103,4 @@ public static SimpleDiscoveryProperties simpleDiscoveryProperties(@Nonnull Simpl private DiscoveryUtils() { } -} +} \ No newline at end of file From c0252b622792e7cd996ca356f6a798c2b92edd25 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 11:21:20 +0800 Subject: [PATCH 05/19] Fix port handling and property setting in ServiceInstanceUtils Default ports are now set to 80 or 443 if the instance port is non-positive. Also, setHost and setPort are now called when copying properties to DefaultServiceInstance, and the URI is set directly from the source instance. --- .../service/util/ServiceInstanceUtils.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java index 3cc7db4..48d7fe5 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtils.java @@ -51,6 +51,7 @@ import static io.microsphere.util.StringUtils.EMPTY_STRING; import static io.microsphere.util.StringUtils.EMPTY_STRING_ARRAY; import static io.microsphere.util.StringUtils.isBlank; +import static java.lang.String.valueOf; import static java.net.URI.create; import static java.util.Collections.emptyList; @@ -102,12 +103,16 @@ public static String getUriString(ServiceInstance instance) { boolean isSecure = instance.isSecure(); String prefix = isSecure ? "https://" : "http://"; String host = instance.getHost(); - String port = String.valueOf(instance.getPort()); - StringBuilder urlStringBuilder = new StringBuilder((isSecure ? 9 : 8) + host.length() + port.length()); + int port = instance.getPort(); + if (port <= 0) { + port = isSecure ? 443 : 80; + } + String portString = valueOf(port); + StringBuilder urlStringBuilder = new StringBuilder((isSecure ? 9 : 8) + host.length() + portString.length()); urlStringBuilder.append(prefix) .append(host) .append(COLON_CHAR) - .append(port); + .append(portString); return urlStringBuilder.toString(); } @@ -171,8 +176,9 @@ public static String removeMetadata(ServiceInstance serviceInstance, String meta public static void setProperties(ServiceInstance source, DefaultServiceInstance target) { target.setInstanceId(source.getInstanceId()); target.setServiceId(source.getServiceId()); - URI uri = getUri(source); - target.setUri(uri); + target.setUri(source.getUri()); + target.setHost(source.getHost()); + target.setPort(source.getPort()); Map metadata = source.getMetadata(); metadata.clear(); metadata.putAll(source.getMetadata()); From c9a58768c457adf3a917a96afb2107732aa8632b Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 11:21:25 +0800 Subject: [PATCH 06/19] Add tests for URI handling without explicit port Added test cases to verify that default ports are appended to URIs without explicit port numbers in ServiceInstanceUtils. Also enhanced testGetUri to check for correct default port assignment and consistency with DefaultServiceInstance.getUri. --- .../util/ServiceInstanceUtilsTest.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtilsTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtilsTest.java index 18ef90c..2b065eb 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtilsTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/util/ServiceInstanceUtilsTest.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test; import org.springframework.cloud.client.DefaultServiceInstance; +import java.net.URI; import java.util.Collection; import static io.microsphere.collection.Lists.ofList; @@ -128,9 +129,27 @@ void testGetUriString() { assertEquals(uriString, getUriString(this.serviceInstance)); } + @Test + void testGetUriStringWithoutPort() { + String uriString = "http://localhost"; + this.serviceInstance.setUri(create(uriString)); + assertEquals(uriString + ":80", getUriString(this.serviceInstance)); + + uriString = "https://localhost"; + this.serviceInstance.setUri(create(uriString)); + assertEquals(uriString + ":443", getUriString(this.serviceInstance)); + } + @Test void testGetUri() { - assertEquals(create("http://localhost:8080"), getUri(this.serviceInstance)); + URI uri = getUri(this.serviceInstance); + assertEquals(create("http://localhost:8080"), uri); + assertEquals(DefaultServiceInstance.getUri(this.serviceInstance), uri); + + uri = create("https://localhost"); + this.serviceInstance.setUri(uri); + uri = getUri(this.serviceInstance); + assertEquals(create("https://localhost:443"), uri); } @Test From 40f0b7c1f1332a9f024616c2584f3d89458cdda6 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 13:20:49 +0800 Subject: [PATCH 07/19] Add spring-cloud-loadbalancer as optional dependency Included the 'spring-cloud-loadbalancer' dependency as optional in the module's pom.xml to support load balancing features when needed. --- microsphere-spring-cloud-commons/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/microsphere-spring-cloud-commons/pom.xml b/microsphere-spring-cloud-commons/pom.xml index 41fd299..d7abbef 100644 --- a/microsphere-spring-cloud-commons/pom.xml +++ b/microsphere-spring-cloud-commons/pom.xml @@ -67,6 +67,11 @@ true + + org.springframework.cloud + spring-cloud-loadbalancer + true + From 598ad4cf4a1615e54ecdaf9e7be5011085892a4f Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 13:20:55 +0800 Subject: [PATCH 08/19] Add property constants for Load-Balancer and Util Introduced LOAD_BALANCER_ENABLED_PROPERTY_NAME and UTIL_ENABLED_PROPERTY_NAME to define property names for enabling Spring Cloud Load-Balancer and Util features. These additions improve configuration clarity and consistency. --- .../SpringCloudPropertyConstants.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/commons/constants/SpringCloudPropertyConstants.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/commons/constants/SpringCloudPropertyConstants.java index bcabfd5..0fce3f3 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/commons/constants/SpringCloudPropertyConstants.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/commons/constants/SpringCloudPropertyConstants.java @@ -20,6 +20,7 @@ import io.microsphere.annotation.ConfigurationProperty; import org.springframework.cloud.client.CommonsClientAutoConfiguration; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration; +import org.springframework.cloud.commons.util.UtilAutoConfiguration; import static io.microsphere.annotation.ConfigurationProperty.APPLICATION_SOURCE; import static io.microsphere.constants.PropertyConstants.ENABLED_PROPERTY_NAME; @@ -68,4 +69,29 @@ public interface SpringCloudPropertyConstants { source = APPLICATION_SOURCE ) String FEATURES_ENABLED_PROPERTY_NAME = SPRING_CLOUD_PROPERTY_PREFIX + "features." + ENABLED_PROPERTY_NAME; + + /** + * The property name for enabling Spring Cloud Load-Balancer : "spring.cloud.loadbalancer.enabled" + * + * @see org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration + */ + @ConfigurationProperty( + type = boolean.class, + defaultValue = "true", + source = APPLICATION_SOURCE + ) + String LOAD_BALANCER_ENABLED_PROPERTY_NAME = SPRING_CLOUD_PROPERTY_PREFIX + "loadbalancer." + ENABLED_PROPERTY_NAME; + + + /** + * The property name for enabling Spring Cloud Util : "spring.cloud.util.enabled" + * + * @see UtilAutoConfiguration + */ + @ConfigurationProperty( + type = boolean.class, + defaultValue = "true", + source = APPLICATION_SOURCE + ) + String UTIL_ENABLED_PROPERTY_NAME = SPRING_CLOUD_PROPERTY_PREFIX + "util." + ENABLED_PROPERTY_NAME; } \ No newline at end of file From 89b35d4f558454245f20b59bc02017225a6a8018 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 13:21:02 +0800 Subject: [PATCH 09/19] Add unit test for SpringCloudPropertyConstants Introduces a JUnit test class to verify the values of constants defined in SpringCloudPropertyConstants. Ensures that property names and prefixes are correctly set. --- .../SpringCloudPropertyConstantsTest.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/constants/SpringCloudPropertyConstantsTest.java diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/constants/SpringCloudPropertyConstantsTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/constants/SpringCloudPropertyConstantsTest.java new file mode 100644 index 0000000..41b9a19 --- /dev/null +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/constants/SpringCloudPropertyConstantsTest.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 io.microsphere.spring.cloud.commons.constants; + + +import org.junit.jupiter.api.Test; + +import static io.microsphere.spring.cloud.commons.constants.SpringCloudPropertyConstants.FEATURES_ENABLED_PROPERTY_NAME; +import static io.microsphere.spring.cloud.commons.constants.SpringCloudPropertyConstants.LOAD_BALANCER_ENABLED_PROPERTY_NAME; +import static io.microsphere.spring.cloud.commons.constants.SpringCloudPropertyConstants.SERVICE_REGISTRY_AUTO_REGISTRATION_ENABLED_PROPERTY_NAME; +import static io.microsphere.spring.cloud.commons.constants.SpringCloudPropertyConstants.SERVICE_REGISTRY_PROPERTY_PREFIX; +import static io.microsphere.spring.cloud.commons.constants.SpringCloudPropertyConstants.SPRING_CLOUD_PROPERTY_PREFIX; +import static io.microsphere.spring.cloud.commons.constants.SpringCloudPropertyConstants.UTIL_ENABLED_PROPERTY_NAME; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link SpringCloudPropertyConstants} Test + * + * @author Mercy + * @see SpringCloudPropertyConstants + * @since 1.0.0 + */ +class SpringCloudPropertyConstantsTest { + + @Test + void testConstants() { + assertEquals("spring.cloud.", SPRING_CLOUD_PROPERTY_PREFIX); + assertEquals("spring.cloud.service-registry.", SERVICE_REGISTRY_PROPERTY_PREFIX); + assertEquals("spring.cloud.service-registry.auto-registration.enabled", SERVICE_REGISTRY_AUTO_REGISTRATION_ENABLED_PROPERTY_NAME); + assertEquals("spring.cloud.features.enabled", FEATURES_ENABLED_PROPERTY_NAME); + assertEquals("spring.cloud.loadbalancer.enabled", LOAD_BALANCER_ENABLED_PROPERTY_NAME); + assertEquals("spring.cloud.util.enabled", UTIL_ENABLED_PROPERTY_NAME); + } +} \ No newline at end of file From a5af0a5b0ee1862a1e28391b9ea8402c405750f7 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 13:21:08 +0800 Subject: [PATCH 10/19] Add ConditionalOnLoadBalancerEnabled annotation Introduces a custom annotation that meta-annotates @ConditionalOnProperty for enabling LoadBalancer based on the 'LOAD_BALANCER_ENABLED_PROPERTY_NAME' property. This simplifies conditional bean registration for LoadBalancer-related components. --- .../ConditionalOnLoadBalancerEnabled.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabled.java diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabled.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabled.java new file mode 100644 index 0000000..5b04c06 --- /dev/null +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabled.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 io.microsphere.spring.cloud.loadbalancer.condition; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static io.microsphere.spring.cloud.commons.constants.SpringCloudPropertyConstants.LOAD_BALANCER_ENABLED_PROPERTY_NAME; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * The conditional annotation meta-annotates {@link ConditionalOnProperty @ConditionalOnProperty} for + * LoadBalancer enabled. + * + * @author Mercy + * @see org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration + * @see ConditionalOnProperty + * @since 1.0.0 + */ +@Retention(RUNTIME) +@Target({TYPE, METHOD}) +@Documented +@ConditionalOnProperty(name = LOAD_BALANCER_ENABLED_PROPERTY_NAME, havingValue = "true", matchIfMissing = true) +public @interface ConditionalOnLoadBalancerEnabled { +} \ No newline at end of file From 2567b4eafbb0fb5d912fcaa7301d0376cb94bbec Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 13:21:15 +0800 Subject: [PATCH 11/19] Add test for ConditionalOnLoadBalancerEnabled Introduces ConditionalOnLoadBalancerEnabledTest to verify bean presence based on the 'spring.cloud.loadbalancer.enabled' property. Ensures correct conditional behavior in Spring context. --- .../ConditionalOnLoadBalancerEnabledTest.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java new file mode 100644 index 0000000..d794f30 --- /dev/null +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 io.microsphere.spring.cloud.loadbalancer.condition; + +import org.junit.jupiter.api.Test; + +import java.util.Properties; + +import static com.alibaba.spring.util.BeanUtils.isBeanPresent; +import static io.microsphere.spring.test.util.SpringTestUtils.testInSpringContainer; +import static java.lang.System.getProperties; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link ConditionalOnLoadBalancerEnabled @ConditionalOnLoadBalancerEnabled} Test + * + * @author Mercy + * @see ConditionalOnLoadBalancerEnabled + * @since 1.0.0 + */ +@ConditionalOnLoadBalancerEnabled +public class ConditionalOnLoadBalancerEnabledTest { + + @Test + void testConfigBeanPresent() { + testConfigBean(true); + } + + @Test + void testConfigBeanAbsent() { + Properties properties = getProperties(); + try { + properties.setProperty("spring.cloud.loadbalancer.enabled", "false"); + testConfigBean(false); + } finally { + properties.remove("spring.cloud.loadbalancer.enabled"); + } + } + + void testConfigBean(boolean present) { + testInSpringContainer(context -> { + assertEquals(present, isBeanPresent(context, getClass())); + }, getClass()); + } +} From b9612662db5c805eb4ae09f34a385b1fa85a613a Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 13:21:20 +0800 Subject: [PATCH 12/19] Add ConditionalOnUtilEnabled annotation Introduces a new meta-annotation that applies @ConditionalOnProperty for the UtilAutoConfiguration enabled property. This simplifies conditional configuration based on the UTIL_ENABLED_PROPERTY_NAME property. --- .../condition/ConditionalOnUtilEnabled.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabled.java diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabled.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabled.java new file mode 100644 index 0000000..a24ed4c --- /dev/null +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabled.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 io.microsphere.spring.cloud.commons.condition; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.commons.util.UtilAutoConfiguration; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static io.microsphere.spring.cloud.commons.constants.SpringCloudPropertyConstants.UTIL_ENABLED_PROPERTY_NAME; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * The conditional annotation meta-annotates {@link ConditionalOnProperty @ConditionalOnProperty} for + * {@link UtilAutoConfiguration} enabled. + * + * @author Mercy + * @see UtilAutoConfiguration + * @see ConditionalOnProperty + * @since 1.0.0 + */ +@Retention(RUNTIME) +@Target({TYPE, METHOD}) +@Documented +@ConditionalOnProperty(name = UTIL_ENABLED_PROPERTY_NAME, matchIfMissing = true) +public @interface ConditionalOnUtilEnabled { +} \ No newline at end of file From 8e4e003c9dd1e2778363940382f0614b63492656 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 13:21:24 +0800 Subject: [PATCH 13/19] Add test for ConditionalOnUtilEnabled annotation Introduces ConditionalOnUtilEnabledTest to verify bean presence based on the 'spring.cloud.util.enabled' property. Ensures correct conditional behavior in Spring container. --- .../ConditionalOnUtilEnabledTest.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java new file mode 100644 index 0000000..74bd864 --- /dev/null +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 io.microsphere.spring.cloud.commons.condition; + +import org.junit.jupiter.api.Test; + +import java.util.Properties; + +import static com.alibaba.spring.util.BeanUtils.isBeanPresent; +import static io.microsphere.spring.test.util.SpringTestUtils.testInSpringContainer; +import static java.lang.System.getProperties; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link ConditionalOnUtilEnabled} Test + * + * @author Mercy + * @see ConditionalOnUtilEnabled + * @since 1.0.0 + */ +@ConditionalOnUtilEnabled +public class ConditionalOnUtilEnabledTest { + + @Test + void testConfigBeanPresent() { + testConfigBean(true); + } + + @Test + void testConfigBeanAbsent() { + Properties properties = getProperties(); + try { + properties.setProperty("spring.cloud.util.enabled", "false"); + testConfigBean(false); + } finally { + properties.remove("spring.cloud.util.enabled"); + } + } + + void testConfigBean(boolean present) { + testInSpringContainer(context -> { + assertEquals(present, isBeanPresent(context, getClass())); + }, getClass()); + } +} From f2209ad716893523a73e7d8e174e048edfe4e546 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 13:24:12 +0800 Subject: [PATCH 14/19] Fix test class reference in condition test cases Replaced usage of getClass() with explicit test class references in ConditionalOnUtilEnabledTest and ConditionalOnLoadBalancerEnabledTest to ensure correct bean presence checks. --- .../commons/condition/ConditionalOnUtilEnabledTest.java | 6 +++--- .../condition/ConditionalOnLoadBalancerEnabledTest.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java index 74bd864..4f9696c 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java @@ -54,7 +54,7 @@ void testConfigBeanAbsent() { void testConfigBean(boolean present) { testInSpringContainer(context -> { - assertEquals(present, isBeanPresent(context, getClass())); - }, getClass()); + assertEquals(present, isBeanPresent(context, ConditionalOnUtilEnabledTest.class)); + }, ConditionalOnUtilEnabledTest.class); } -} +} \ No newline at end of file diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java index d794f30..f9d1cca 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java @@ -54,7 +54,7 @@ void testConfigBeanAbsent() { void testConfigBean(boolean present) { testInSpringContainer(context -> { - assertEquals(present, isBeanPresent(context, getClass())); - }, getClass()); + assertEquals(present, isBeanPresent(context, ConditionalOnLoadBalancerEnabledTest.class)); + }, ConditionalOnLoadBalancerEnabledTest.class); } -} +} \ No newline at end of file From 08d4788f15c9ec411c4b9aa91b7743203afc3993 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 15:40:30 +0800 Subject: [PATCH 15/19] Update BeanUtils import to microsphere package in tests Replaced imports of isBeanPresent from com.alibaba.spring.util.BeanUtils with io.microsphere.spring.beans.BeanUtils in ConditionalOnUtilEnabledTest and ConditionalOnLoadBalancerEnabledTest to reflect package changes. --- .../cloud/commons/condition/ConditionalOnUtilEnabledTest.java | 2 +- .../condition/ConditionalOnLoadBalancerEnabledTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java index 4f9696c..14a9895 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java @@ -21,7 +21,7 @@ import java.util.Properties; -import static com.alibaba.spring.util.BeanUtils.isBeanPresent; +import static io.microsphere.spring.beans.BeanUtils.isBeanPresent; import static io.microsphere.spring.test.util.SpringTestUtils.testInSpringContainer; import static java.lang.System.getProperties; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java index f9d1cca..831dc36 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java @@ -21,7 +21,7 @@ import java.util.Properties; -import static com.alibaba.spring.util.BeanUtils.isBeanPresent; +import static io.microsphere.spring.beans.BeanUtils.isBeanPresent; import static io.microsphere.spring.test.util.SpringTestUtils.testInSpringContainer; import static java.lang.System.getProperties; import static org.junit.jupiter.api.Assertions.assertEquals; From 8489f68f470ab1ee6cc1de193e2261124b237444 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 17:25:13 +0800 Subject: [PATCH 16/19] Refactor conditional property tests to use shared base class Introduced ConditionalOnPropertyEnabledTest as a reusable abstract test for @ConditionalOnProperty-based conditions. Updated ConditionalOnFeaturesEnabledTest, ConditionalOnUtilEnabledTest, and ConditionalOnLoadBalancerEnabledTest to extend this new base class, reducing code duplication and improving maintainability. Also updated ConditionalOnFeaturesEnabled to set matchIfMissing=true directly in the annotation. --- .../ConditionalOnFeaturesEnabled.java | 12 +- .../ConditionalOnFeaturesEnabledTest.java | 34 +---- .../ConditionalOnUtilEnabledTest.java | 33 +---- .../ConditionalOnLoadBalancerEnabledTest.java | 33 +---- .../ConditionalOnPropertyEnabledTest.java | 122 ++++++++++++++++++ 5 files changed, 130 insertions(+), 104 deletions(-) create mode 100644 microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/test/ConditionalOnPropertyEnabledTest.java diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/condition/ConditionalOnFeaturesEnabled.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/condition/ConditionalOnFeaturesEnabled.java index 1ce3f27..d7058b9 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/condition/ConditionalOnFeaturesEnabled.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/condition/ConditionalOnFeaturesEnabled.java @@ -21,7 +21,6 @@ import org.springframework.cloud.client.CommonsClientAutoConfiguration; import org.springframework.cloud.client.actuator.FeaturesEndpoint; import org.springframework.cloud.client.actuator.HasFeatures; -import org.springframework.core.annotation.AliasFor; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -47,15 +46,6 @@ @Retention(RUNTIME) @Target({TYPE, METHOD}) @Documented -@ConditionalOnProperty(name = FEATURES_ENABLED_PROPERTY_NAME) +@ConditionalOnProperty(name = FEATURES_ENABLED_PROPERTY_NAME, matchIfMissing = true) public @interface ConditionalOnFeaturesEnabled { - - /** - * Specify if the condition should match if the property is not set. Defaults to - * {@code true}. - * - * @return if the condition should match if the property is missing - */ - @AliasFor(annotation = ConditionalOnProperty.class, attribute = "matchIfMissing") - boolean matchIfMissing() default true; } diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/condition/ConditionalOnFeaturesEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/condition/ConditionalOnFeaturesEnabledTest.java index 6e57810..80986d9 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/condition/ConditionalOnFeaturesEnabledTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/condition/ConditionalOnFeaturesEnabledTest.java @@ -24,36 +24,8 @@ * @since 1.0.0 */ -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; +import io.microsphere.spring.cloud.test.ConditionalOnPropertyEnabledTest; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -@ExtendWith(SpringExtension.class) -@ContextConfiguration(classes = { - ConditionalOnFeaturesEnabledTest.FeaturesConfiguration.class -}) -@TestPropertySource( - properties = { - "spring.cloud.features.enabled=true" - } -) -class ConditionalOnFeaturesEnabledTest { - - @ConditionalOnFeaturesEnabled - static class FeaturesConfiguration { - } - - @Autowired - private ObjectProvider featuresConfigurationProvider; - - @Test - void test() { - assertNotNull(featuresConfigurationProvider.getIfAvailable()); - } +@ConditionalOnFeaturesEnabled +class ConditionalOnFeaturesEnabledTest extends ConditionalOnPropertyEnabledTest { } diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java index 14a9895..ce62854 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/commons/condition/ConditionalOnUtilEnabledTest.java @@ -17,14 +17,7 @@ package io.microsphere.spring.cloud.commons.condition; -import org.junit.jupiter.api.Test; - -import java.util.Properties; - -import static io.microsphere.spring.beans.BeanUtils.isBeanPresent; -import static io.microsphere.spring.test.util.SpringTestUtils.testInSpringContainer; -import static java.lang.System.getProperties; -import static org.junit.jupiter.api.Assertions.assertEquals; +import io.microsphere.spring.cloud.test.ConditionalOnPropertyEnabledTest; /** * {@link ConditionalOnUtilEnabled} Test @@ -34,27 +27,5 @@ * @since 1.0.0 */ @ConditionalOnUtilEnabled -public class ConditionalOnUtilEnabledTest { - - @Test - void testConfigBeanPresent() { - testConfigBean(true); - } - - @Test - void testConfigBeanAbsent() { - Properties properties = getProperties(); - try { - properties.setProperty("spring.cloud.util.enabled", "false"); - testConfigBean(false); - } finally { - properties.remove("spring.cloud.util.enabled"); - } - } - - void testConfigBean(boolean present) { - testInSpringContainer(context -> { - assertEquals(present, isBeanPresent(context, ConditionalOnUtilEnabledTest.class)); - }, ConditionalOnUtilEnabledTest.class); - } +public class ConditionalOnUtilEnabledTest extends ConditionalOnPropertyEnabledTest { } \ No newline at end of file diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java index 831dc36..d251003 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/loadbalancer/condition/ConditionalOnLoadBalancerEnabledTest.java @@ -17,14 +17,7 @@ package io.microsphere.spring.cloud.loadbalancer.condition; -import org.junit.jupiter.api.Test; - -import java.util.Properties; - -import static io.microsphere.spring.beans.BeanUtils.isBeanPresent; -import static io.microsphere.spring.test.util.SpringTestUtils.testInSpringContainer; -import static java.lang.System.getProperties; -import static org.junit.jupiter.api.Assertions.assertEquals; +import io.microsphere.spring.cloud.test.ConditionalOnPropertyEnabledTest; /** * {@link ConditionalOnLoadBalancerEnabled @ConditionalOnLoadBalancerEnabled} Test @@ -34,27 +27,5 @@ * @since 1.0.0 */ @ConditionalOnLoadBalancerEnabled -public class ConditionalOnLoadBalancerEnabledTest { - - @Test - void testConfigBeanPresent() { - testConfigBean(true); - } - - @Test - void testConfigBeanAbsent() { - Properties properties = getProperties(); - try { - properties.setProperty("spring.cloud.loadbalancer.enabled", "false"); - testConfigBean(false); - } finally { - properties.remove("spring.cloud.loadbalancer.enabled"); - } - } - - void testConfigBean(boolean present) { - testInSpringContainer(context -> { - assertEquals(present, isBeanPresent(context, ConditionalOnLoadBalancerEnabledTest.class)); - }, ConditionalOnLoadBalancerEnabledTest.class); - } +public class ConditionalOnLoadBalancerEnabledTest extends ConditionalOnPropertyEnabledTest { } \ No newline at end of file diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/test/ConditionalOnPropertyEnabledTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/test/ConditionalOnPropertyEnabledTest.java new file mode 100644 index 0000000..42ec97f --- /dev/null +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/test/ConditionalOnPropertyEnabledTest.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 io.microsphere.spring.cloud.test; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Conditional; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotationMetadata; + +import java.util.Properties; +import java.util.Set; + +import static io.microsphere.collection.SetUtils.newLinkedHashSet; +import static io.microsphere.spring.beans.BeanUtils.isBeanPresent; +import static io.microsphere.spring.core.annotation.AnnotationUtils.getAnnotationAttributes; +import static io.microsphere.spring.test.util.SpringTestUtils.testInSpringContainer; +import static io.microsphere.util.ArrayUtils.isEmpty; +import static java.lang.String.valueOf; +import static java.lang.System.getProperties; +import static org.apache.commons.io.IOUtils.length; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.core.type.AnnotationMetadata.introspect; +import static org.springframework.util.StringUtils.hasText; + +/** + * Abstract test class for {@link ConditionalOnProperty @ConditionalOnProperty} On Enabled + * + * @author Mercy + * @see ConditionalOnProperty + * @since 1.0.0 + */ +public abstract class ConditionalOnPropertyEnabledTest { + + private AnnotationAttributes annotationAttributes; + + @BeforeEach + void setUp() { + AnnotationMetadata annotationMetadata = introspect(getClass()); + this.annotationAttributes = getAnnotationAttributes(annotationMetadata, ConditionalOnProperty.class); + } + + @Test + void testConditionalOnPropertyEnabled() { + if (matchIfMissing()) { + testBean(true); + } else { + testConditionalOnPropertyEnabled(true); + } + } + + @Test + void testConditionalOnPropertyDisabled() { + testConditionalOnPropertyEnabled(false); + } + + /** + * Whether match if missing + * + * @return {@code true} if match if missing + */ + protected boolean matchIfMissing() { + return this.annotationAttributes.getBoolean("matchIfMissing"); + } + + /** + * Get the property names of the {@link Conditional @Conditional} + * + * @return property names + */ + protected Set getPropertyNames() { + String prefix = this.annotationAttributes.getString("prefix"); + String[] names = this.annotationAttributes.getStringArray("name"); + if (isEmpty(names)) { + names = this.annotationAttributes.getStringArray("value"); + } + boolean hasPrefix = hasText(prefix); + Set propertyNames = newLinkedHashSet(length(names)); + for (String name : names) { + String propertyName = hasPrefix ? prefix + name : name; + propertyNames.add(propertyName); + } + return propertyNames; + } + + protected void testConditionalOnPropertyEnabled(boolean enabled) { + Set propertyNames = getPropertyNames(); + Properties properties = getProperties(); + try { + for (String propertyName : propertyNames) { + properties.setProperty(propertyName, valueOf(enabled)); + } + testBean(enabled); + } finally { + for (String propertyName : propertyNames) { + properties.remove(propertyName); + } + } + } + + protected void testBean(boolean present) { + testInSpringContainer(context -> { + assertEquals(present, isBeanPresent(context, getClass())); + }, getClass()); + } +} \ No newline at end of file From 0526ba9a50e8eebbcd0c058d011d78362ab44d28 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 19:04:52 +0800 Subject: [PATCH 17/19] Handle non-blocking thread in toList utility method Updated the toList method in ReactiveDiscoveryClientAdapter to use a non-blocking approach when called from a non-blocking thread, improving compatibility with reactive environments. --- .../discovery/ReactiveDiscoveryClientAdapter.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/ReactiveDiscoveryClientAdapter.java b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/ReactiveDiscoveryClientAdapter.java index 12f55e1..652ca76 100644 --- a/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/ReactiveDiscoveryClientAdapter.java +++ b/microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/discovery/ReactiveDiscoveryClientAdapter.java @@ -21,9 +21,13 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import java.util.List; +import static io.microsphere.lang.function.ThrowableSupplier.execute; +import static reactor.core.scheduler.Schedulers.isInNonBlockingThread; + /** * An adapter {@link DiscoveryClient} class based on {@link ReactiveDiscoveryClient} * @@ -67,6 +71,10 @@ public int getOrder() { } static List toList(Flux flux) { - return flux.collectList().block(); + Mono> mono = flux.collectList(); + if (isInNonBlockingThread()) { + return execute(() -> mono.toFuture().get()); + } + return mono.block(); } } \ No newline at end of file From 3c8af378dcf3e91adc4fc2c7f31f9e05ada495b8 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 19:04:57 +0800 Subject: [PATCH 18/19] Add tests for ReactiveDiscoveryClientAdapter.toList Introduced test cases to verify the toList utility method with different schedulers in ReactiveDiscoveryClientAdapterTest. Ensures correct conversion of Flux to List under various scheduling scenarios. --- .../ReactiveDiscoveryClientAdapterTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/ReactiveDiscoveryClientAdapterTest.java b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/ReactiveDiscoveryClientAdapterTest.java index c6ae138..2f65a00 100644 --- a/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/ReactiveDiscoveryClientAdapterTest.java +++ b/microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/discovery/ReactiveDiscoveryClientAdapterTest.java @@ -26,15 +26,22 @@ import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClient; import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryProperties; +import reactor.core.Disposable; +import reactor.core.publisher.Flux; +import reactor.core.scheduler.Scheduler; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; import static io.microsphere.collection.Lists.ofList; +import static io.microsphere.spring.cloud.client.discovery.ReactiveDiscoveryClientAdapter.toList; import static io.microsphere.spring.cloud.client.service.util.ServiceInstanceUtilsTest.createDefaultServiceInstance; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; +import static reactor.core.scheduler.Schedulers.immediate; +import static reactor.core.scheduler.Schedulers.newSingle; /** * {@link ReactiveDiscoveryClientAdapter} @@ -97,4 +104,21 @@ void testProbe() { void testGetOrder() { assertEquals(this.client.getOrder(), this.adapter.getOrder()); } + + @Test + void testToList() throws Exception { + assertList(immediate(), "1,2,3"); + assertList(newSingle("test"), "1,2,3"); + } + + void assertList(Scheduler scheduler, T... values) throws Exception { + Flux flux = Flux.just(values); + Disposable disposable = scheduler.schedule(() -> { + List list = toList(flux); + assertEquals(ofList(values), list); + }); + if (disposable instanceof Callable) { + ((Callable) disposable).call(); + } + } } \ No newline at end of file From fff9766956d94e95d55a67ba7c858cc196ac6149 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 31 Oct 2025 19:15:39 +0800 Subject: [PATCH 19/19] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f43ba8f..b2c8a7b 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ pom.xml: | **Branches** | **Purpose** | **Latest Version** | |--------------|--------------------------------------------------|--------------------| -| **0.2.x** | Compatible with Spring Cloud 2022.0.x - 2025.0.x | 0.2.3 | -| **0.1.x** | Compatible with Spring Cloud Hoxton - 2021.0.x | 0.1.3 | +| **0.2.x** | Compatible with Spring Cloud 2022.0.x - 2025.0.x | 0.2.4 | +| **0.1.x** | Compatible with Spring Cloud Hoxton - 2021.0.x | 0.1.4 | Then add the specific modules you need: