diff --git a/example/example-consumer-server/src/main/kotlin/me/ahoo/coapi/example/consumer/ConsumerServer.kt b/example/example-consumer-server/src/main/kotlin/me/ahoo/coapi/example/consumer/ConsumerServer.kt index 111f3f4..3efd306 100644 --- a/example/example-consumer-server/src/main/kotlin/me/ahoo/coapi/example/consumer/ConsumerServer.kt +++ b/example/example-consumer-server/src/main/kotlin/me/ahoo/coapi/example/consumer/ConsumerServer.kt @@ -34,7 +34,7 @@ import org.springframework.boot.runApplication TodoClient::class ] ) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = ["me.ahoo.coapi.example.consumer.client"]) class ConsumerServer fun main(args: Array) { diff --git a/example/example-consumer-server/src/main/resources/application.yaml b/example/example-consumer-server/src/main/resources/application.yaml index 954896c..1880666 100644 --- a/example/example-consumer-server/src/main/resources/application.yaml +++ b/example/example-consumer-server/src/main/resources/application.yaml @@ -19,6 +19,8 @@ spring: - host: localhost port: 8010 coapi: + base-packages: + - me.ahoo.coapi.example.consumer.client clients: ServiceApiClientUseFilterBeanName: reactive: @@ -29,4 +31,4 @@ coapi: reactive: filter: types: - - org.springframework.cloud.client.loadbalancer.reactive.LoadBalancedExchangeFilterFunction \ No newline at end of file + - org.springframework.cloud.client.loadbalancer.reactive.LoadBalancedExchangeFilterFunction diff --git a/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/AutoCoApiRegistrar.kt b/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/AutoCoApiRegistrar.kt index 0f45448..00f388e 100644 --- a/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/AutoCoApiRegistrar.kt +++ b/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/AutoCoApiRegistrar.kt @@ -20,18 +20,45 @@ import me.ahoo.coapi.spring.CoApiDefinition.Companion.toCoApiDefinition import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition import org.springframework.boot.autoconfigure.AutoConfigurationPackages import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider +import org.springframework.core.env.Environment import org.springframework.core.type.AnnotationMetadata import org.springframework.core.type.filter.AnnotationTypeFilter class AutoCoApiRegistrar : AbstractCoApiRegistrar() { + private fun getCoApiBasePackages(): List { + val basePackages = env.getProperty(CoApiProperties.COAPI_BASE_PACKAGES) + if (basePackages?.isNotBlank() == true) { + return basePackages.split(",").distinct().toList() + } + var currentIndex = 0 + buildList { + while (true) { + val basePackage = env.getProperty("${CoApiProperties.COAPI_BASE_PACKAGES}[$currentIndex]") + if (basePackage.isNullOrBlank()) { + return this + } + add(basePackage) + currentIndex++ + } + } + } + + private fun getScanBasePackages(): List { + val coApiBasePackages = getCoApiBasePackages() + if (coApiBasePackages.isNotEmpty()) { + return coApiBasePackages + } + return AutoConfigurationPackages.get(appContext) + } + override fun getCoApiDefinitions(importingClassMetadata: AnnotationMetadata): Set { - val scanBasePackages = AutoConfigurationPackages.get(appContext).toSet() + val scanBasePackages = getScanBasePackages() return scanBasePackages.toApiClientDefinitions() } - private fun Set.toApiClientDefinitions(): Set { - val scanner = ApiClientScanner() + private fun List.toApiClientDefinitions(): Set { + val scanner = ApiClientScanner(false, env) return flatMap { basePackage -> scanner.findCandidateComponents(basePackage) }.map { beanDefinition -> @@ -40,7 +67,8 @@ class AutoCoApiRegistrar : AbstractCoApiRegistrar() { } } -class ApiClientScanner : ClassPathScanningCandidateComponentProvider(false) { +class ApiClientScanner(useDefaultFilters: Boolean, environment: Environment) : + ClassPathScanningCandidateComponentProvider(useDefaultFilters, environment) { init { addIncludeFilter(AnnotationTypeFilter(CoApi::class.java)) } diff --git a/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiProperties.kt b/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiProperties.kt index 9601abc..2f5c757 100644 --- a/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiProperties.kt +++ b/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiProperties.kt @@ -25,8 +25,13 @@ const val ENABLED_SUFFIX_KEY = ".enabled" data class CoApiProperties( @DefaultValue("true") var enabled: Boolean = true, val mode: ClientMode = ClientMode.AUTO, + val basePackages: List = emptyList(), val clients: Map = emptyMap(), ) : ClientProperties { + companion object { + const val COAPI_BASE_PACKAGES = "$COAPI_PREFIX.base-packages" + } + override fun getFilter(coApiName: String): ClientProperties.FilterDefinition { return clients[coApiName]?.reactive?.filter ?: ClientProperties.FilterDefinition() } diff --git a/spring-boot-starter/src/test/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiAutoConfigurationTest.kt b/spring-boot-starter/src/test/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiAutoConfigurationTest.kt index cf7cbdf..1e3cfe7 100644 --- a/spring-boot-starter/src/test/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiAutoConfigurationTest.kt +++ b/spring-boot-starter/src/test/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiAutoConfigurationTest.kt @@ -95,6 +95,67 @@ class CoApiAutoConfigurationTest { context.getBean(ServiceApiClientUseFilterType::class.java) } } + + @Test + fun basePackages() { + ApplicationContextRunner() + .withPropertyValues("github.url=https://api.github.com") + .withPropertyValues("${CoApiProperties.COAPI_BASE_PACKAGES}=me.ahoo.coapi.spring.boot.starter") + .withPropertyValues(filterNameProperty) + .withPropertyValues(filterTypeProperty) + .withBean("loadBalancerExchangeFilterFunction", LoadBalancedExchangeFilterFunction::class.java, { mockk() }) + .withUserConfiguration(WebClientAutoConfiguration::class.java) + .withUserConfiguration(CoApiAutoConfiguration::class.java) + .run { context -> + AssertionsForInterfaceTypes.assertThat(context) + .hasSingleBean(ReactiveHttpExchangeAdapterFactory::class.java) + .hasSingleBean(me.ahoo.coapi.spring.boot.starter.GitHubApiClient::class.java) + } + } + + @Test + fun basePackagesMultiple() { + ApplicationContextRunner() + .withPropertyValues("github.url=https://api.github.com") + .withPropertyValues( + "${CoApiProperties.COAPI_BASE_PACKAGES}=me.ahoo.coapi.spring.boot.starter" + + ",me.ahoo.coapi.example.consumer.client" + ) + .withPropertyValues(filterNameProperty) + .withPropertyValues(filterTypeProperty) + .withBean("loadBalancerExchangeFilterFunction", LoadBalancedExchangeFilterFunction::class.java, { mockk() }) + .withUserConfiguration(WebClientAutoConfiguration::class.java) + .withUserConfiguration(CoApiAutoConfiguration::class.java) + .run { context -> + AssertionsForInterfaceTypes.assertThat(context) + .hasSingleBean(ReactiveHttpExchangeAdapterFactory::class.java) + .hasSingleBean(me.ahoo.coapi.spring.boot.starter.GitHubApiClient::class.java) + .hasSingleBean(ServiceApiClient::class.java) + } + } + + @Test + fun basePackagesYaml() { + ApplicationContextRunner() + .withPropertyValues("github.url=https://api.github.com") + .withPropertyValues( + "${CoApiProperties.COAPI_BASE_PACKAGES}[0]=me.ahoo.coapi.spring.boot.starter" + ) + .withPropertyValues( + "${CoApiProperties.COAPI_BASE_PACKAGES}[1]=me.ahoo.coapi.example.consumer.client" + ) + .withPropertyValues(filterNameProperty) + .withPropertyValues(filterTypeProperty) + .withBean("loadBalancerExchangeFilterFunction", LoadBalancedExchangeFilterFunction::class.java, { mockk() }) + .withUserConfiguration(WebClientAutoConfiguration::class.java) + .withUserConfiguration(CoApiAutoConfiguration::class.java) + .run { context -> + AssertionsForInterfaceTypes.assertThat(context) + .hasSingleBean(ReactiveHttpExchangeAdapterFactory::class.java) + .hasSingleBean(me.ahoo.coapi.spring.boot.starter.GitHubApiClient::class.java) + .hasSingleBean(ServiceApiClient::class.java) + } + } } @SpringBootApplication diff --git a/spring-boot-starter/src/test/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiPropertiesTest.kt b/spring-boot-starter/src/test/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiPropertiesTest.kt index bb6753d..07294c6 100644 --- a/spring-boot-starter/src/test/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiPropertiesTest.kt +++ b/spring-boot-starter/src/test/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiPropertiesTest.kt @@ -35,6 +35,12 @@ class CoApiPropertiesTest { assertThat(properties.enabled, equalTo(true)) } + @Test + fun getBasePackages() { + val properties = CoApiProperties() + assertThat(properties.basePackages, Matchers.empty()) + } + @Test fun getFilterIfDefault() { val properties = CoApiProperties()