Open nehanims opened 2 months ago
To build a REST client in a Kotlin Spring Boot application using Spring's HttpExchange
library, follow these steps:
Ensure that you have the necessary dependencies in your build.gradle.kts
file:
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-webflux")
}
Since Spring 6 introduced the @HttpExchange
annotation, you don't need to enable anything explicitly. Just make sure you're using Spring Boot 3 or later, which includes Spring 6.
Define an interface to represent your API client. Use the @HttpExchange
annotation to declare HTTP requests.
import org.springframework.web.service.annotation.HttpExchange
import org.springframework.web.service.annotation.GetExchange
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestParam
@HttpExchange("/endpoint")
interface OllamaClient {
@GetExchange
fun getSomething(
@RequestHeader("Authorization") token: String,
@RequestParam("param1") param1: String,
@RequestParam("param2") param2: String
): ApiResponse
}
In this example:
"/endpoint"
with the specific API endpoint for the Ollama API.@GetExchange
, @PostExchange
, @PutExchange
, or other HTTP method annotations to map the method to the desired HTTP verb.@RequestHeader
, @RequestParam
, and @RequestBody
as needed.Define a data class that matches the structure of the API response:
data class ApiResponse(
val field1: String,
val field2: Int,
// other fields...
)
To create an instance of your API client, you'll need to define a @Bean
in a configuration class:
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.service.invoker.HttpServiceProxyFactory
import org.springframework.web.service.invoker.HttpServiceProxyFactoryBuilder
@Configuration
class OllamaClientConfig {
@Bean
fun ollamaClient(): OllamaClient {
val webClient = WebClient.builder()
.baseUrl("https://api.ollama.com")
.build()
val factory: HttpServiceProxyFactory = HttpServiceProxyFactoryBuilder.builder(WebClient.builder()).build()
return factory.createClient(OllamaClient::class.java)
}
}
Inject the OllamaClient
into a service class and use it to make API calls:
import org.springframework.stereotype.Service
@Service
class OllamaService(private val ollamaClient: OllamaClient) {
fun getApiData(param1: String, param2: String): ApiResponse {
val token = "Bearer your_token_here" // Replace with your actual token or use a more secure approach
return ollamaClient.getSomething(token, param1, param2)
}
}
Finally, test the client by calling the service method in a controller or a test class:
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
class OllamaController(private val ollamaService: OllamaService) {
@GetMapping("/api-data")
fun getApiData(
@RequestParam param1: String,
@RequestParam param2: String
): ApiResponse {
return ollamaService.getApiData(param1, param2)
}
}
By using Spring's HttpExchange
library, you can create a type-safe and declarative HTTP client to interact with external APIs like the Ollama API. This approach is more streamlined and modern compared to older libraries, and it integrates well with the rest of the Spring ecosystem.
Ollama API reference: https://github.com/ollama/ollama/blob/main/docs/api.md Ollama github discussion about the difference between
/api/generate
and/api/chat
, specifically, this comment explaining the difference based on Ollama's implementation of those APIs, and this interesting point about summarizationSomeone has published this (possibly older) YAML for Ollama API for use with OpenAPI client code generator. It may be different now so reference the official API docs from Ollama above in case there are errors. And only use the generated code as a reference or/to generate request response body models and such. Edit: Issue to provide an official YAML for codegen integration is open in Ollama's repo :https://github.com/ollama/ollama/issues/3383
Use the declarative HTTPInterface to reduce boilerplate: https://medium.com/digitalfrontiers/declarative-rest-clients-with-spring-framework-6-c671be1dfee https://howtodoinjava.com/spring-webflux/http-declarative-http-client-httpexchange/
Some examples from others using Kotlin to talk to Ollama: UsingOkHttp3 UsingOkHTTP Using springAI