Skip to content

Commit

Permalink
feat: support synchronous HTTP client (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ahoo-Wang authored Jan 19, 2024
1 parent fc332f5 commit 15e05c1
Show file tree
Hide file tree
Showing 44 changed files with 932 additions and 93 deletions.
1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/modules/spring/CoApi.spring.main.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,4 @@

dependencies {
compileOnly("org.springframework:spring-context")
compileOnly("org.springframework:spring-webflux")
}
6 changes: 1 addition & 5 deletions api/src/main/kotlin/me/ahoo/coapi/api/CoApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,11 @@
package me.ahoo.coapi.api

import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.client.ExchangeFilterFunction
import kotlin.reflect.KClass

@Target(AnnotationTarget.CLASS)
@Component
annotation class CoApi(
val serviceId: String = "",
val baseUrl: String = "",
val name: String = "",
val filters: Array<String> = [],
val filterTypes: Array<KClass<out ExchangeFilterFunction>> = [],
val name: String = ""
)
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.service.annotation.GetExchange
import reactor.core.publisher.Flux

@CoApi(serviceId = "github-service", filters = ["loadBalancerExchangeFilterFunction"])
@CoApi(serviceId = "github-service")
interface ServiceApiClientUseFilterBeanName {

@GetExchange("repos/{owner}/{repo}/issues")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
package me.ahoo.coapi.example.consumer.client

import me.ahoo.coapi.api.CoApi
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancedExchangeFilterFunction
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.service.annotation.GetExchange
import reactor.core.publisher.Flux

@CoApi(serviceId = "github-service", filterTypes = [LoadBalancedExchangeFilterFunction::class])
@CoApi(serviceId = "github-service")
interface ServiceApiClientUseFilterType {

@GetExchange("repos/{owner}/{repo}/issues")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,15 @@ spring:
provider-service:
- host: localhost
port: 8010

coapi:
clients:
ServiceApiClientUseFilterBeanName:
reactive:
filter:
names:
-loadBalancerExchangeFilterFunction
ServiceApiClientUseFilterType:
reactive:
filter:
types:
- org.springframework.cloud.client.loadbalancer.reactive.LoadBalancedExchangeFilterFunction
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,29 @@ package me.ahoo.coapi.example.consumer

import me.ahoo.coapi.example.consumer.client.GitHubApiClient
import me.ahoo.coapi.example.consumer.client.ServiceApiClient
import me.ahoo.coapi.spring.client.reactive.ReactiveHttpExchangeAdapterFactory
import org.hamcrest.MatcherAssert
import org.hamcrest.Matchers
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest
class ConsumerServerTest {
@Autowired
private lateinit var httpExchangeAdapterFactory: ReactiveHttpExchangeAdapterFactory

@Autowired
private lateinit var gitHubApiClient: GitHubApiClient

@Autowired
private lateinit var serviceApiClient: ServiceApiClient

@Test
fun httpExchangeAdapterFactoryIsNotNull() {
MatcherAssert.assertThat(httpExchangeAdapterFactory, Matchers.notNullValue())
}

@Test
fun getIssueByGitHubApiClient() {
gitHubApiClient.getIssue("Ahoo-Wang", "Wow")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ spring:
name: provider-service









45 changes: 45 additions & 0 deletions example/example-sync/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright [2022-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].
* 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
* 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.
*/

plugins {
application
alias(libs.plugins.kotlin)
alias(libs.plugins.kotlinSpring)
kotlin("kapt")
}

kotlin {
jvmToolchain(17)
}

dependencies {
implementation(platform(project(":dependencies")))
kapt(platform(project(":dependencies")))
implementation(project(":spring-boot-starter"))
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.cloud:spring-cloud-starter-loadbalancer")
kapt("org.springframework.boot:spring-boot-configuration-processor")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.withType<Test> {
useJUnitPlatform()
}

tasks.withType<JavaCompile> {
options.compilerArgs.addAll(listOf("-parameters"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright [2022-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].
* 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
* 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 me.ahoo.coapi.example.sync

import me.ahoo.coapi.spring.EnableCoApi
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@EnableCoApi(
apis = [
GitHubSyncClient::class
]
)
@SpringBootApplication
class ExampleServer

fun main(args: Array<String>) {
runApplication<ExampleServer>(*args)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright [2022-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].
* 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
* 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 me.ahoo.coapi.example.sync

import me.ahoo.coapi.api.CoApi
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.service.annotation.GetExchange

@CoApi(baseUrl = "\${github.url}")
interface GitHubSyncClient {

@GetExchange("repos/{owner}/{repo}/issues")
fun getIssue(@PathVariable owner: String, @PathVariable repo: String): List<Issue>
}

data class Issue(
val url: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright [2022-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].
* 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
* 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 me.ahoo.coapi.example.sync

import me.ahoo.coapi.api.CoApi
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.service.annotation.GetExchange

@CoApi(serviceId = "github-service")
interface GitHubSyncLbClient {

@GetExchange("repos/{owner}/{repo}/issues")
fun getIssue(@PathVariable owner: String, @PathVariable repo: String): List<Issue>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright [2022-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].
* 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
* 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 me.ahoo.coapi.example.sync

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.service.annotation.HttpExchange

@RestController
@HttpExchange("github")
class GithubController(
private val gitHubApiClient: GitHubSyncClient,
private val gitHubLbApiClient: GitHubSyncLbClient
) {

@GetMapping("/baseUrl")
fun baseUrl(): List<Issue> {
return gitHubApiClient.getIssue("Ahoo-Wang", "Wow")
}

@GetMapping("/serviceId")
fun serviceId(): List<Issue> {
return gitHubLbApiClient.getIssue("Ahoo-Wang", "Wow")
}
}
17 changes: 17 additions & 0 deletions example/example-sync/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
server:
port: 8080
github:
url: https://api.github.com

spring:
application:
name: consumer-service
cloud:
discovery:
client:
simple:
instances:
github-service:
- host: api.github.com
secure: true
port: 443
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package me.ahoo.coapi.example.sync

import me.ahoo.coapi.spring.client.sync.SyncHttpExchangeAdapterFactory
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.notNullValue
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest
class ExampleServerTest {
@Autowired
private lateinit var httpExchangeAdapterFactory: SyncHttpExchangeAdapterFactory

@Autowired
private lateinit var gitHubApiClient: GitHubSyncClient

@Autowired
private lateinit var serviceApiClient: GitHubSyncLbClient

@Test
fun httpExchangeAdapterFactoryIsNotNull() {
assertThat(httpExchangeAdapterFactory, notNullValue())
}

@Test
fun getIssueByGitHubApiClient() {
gitHubApiClient.getIssue("Ahoo-Wang", "Wow")
}

@Test
fun getIssueByServiceApiClient() {
serviceApiClient.getIssue("Ahoo-Wang", "Wow")
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ kotlin.code.style=official
ksp.incremental=true
ksp.incremental.log=true
group=me.ahoo.coapi
version=0.2.2
version=0.5.0
description=Streamlining HTTP client definition in Spring 6, CoApi provides zero boilerplate code auto-configuration for more convenient and efficient interface calls.
website=https://github.com/Ahoo-Wang/CoApi
issues=https://github.com/Ahoo-Wang/CoApi/issues
Expand Down
3 changes: 3 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ include(":example-consumer-client")
project(":example-consumer-client").projectDir = file("example/example-consumer-client")
include(":example-consumer-server")
project(":example-consumer-server").projectDir = file("example/example-consumer-server")

include("example-sync")
project(":example-sync").projectDir = file("example/example-sync")
//endregion

7 changes: 7 additions & 0 deletions spring-boot-starter/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
java {
registerFeature("reactiveSupport") {
usingSourceSet(sourceSets[SourceSet.MAIN_SOURCE_SET_NAME])
capability(group.toString(), "reactive-support", version.toString())
}
}

plugins {
alias(libs.plugins.kotlinSpring)
Expand All @@ -18,6 +24,7 @@ plugins {
dependencies {
kapt(platform(project(":dependencies")))
api(project(":spring"))
"reactiveSupportImplementation"("org.springframework:spring-webflux")
api("org.springframework.boot:spring-boot-starter")
kapt("org.springframework.boot:spring-boot-configuration-processor")
kapt("org.springframework.boot:spring-boot-autoconfigure-processor")
Expand Down
Loading

0 comments on commit 15e05c1

Please sign in to comment.