Configuring Multiple GraphQL Endpoints with Apollo-Kotlin in Spring Boot
Project Structure
A typical Spring Boot project setup for Apollo-Kotlin with multiple GraphQL endpoints includes the folloiwng directoyr layout:
.
├── build.gradle.kts
└── src
├── main
│ ├── graphql
│ │ ├── endpointA
│ │ │ ├── SampleQuery.graphql
│ │ │ └── schema.json
│ │ └── endpointB
│ │ ├── AnotherQuery.graphql
│ │ └── schema.json
│ ├── java
│ ├── kotlin
│ │ └── com
│ │ └── example
│ │ ├── Application.kt
│ │ ├── config
│ │ │ ├── ApolloConfig.kt
│ │ │ └── GraphQLConfig.kt
│ │ └── service
│ │ └── GraphQLService.kt
│ └── resources
│ └── application.yml
└── test
├── java
├── kotlin
│ └── com
│ └── example
│ └── ApplicationTests.kt
└── resources
Build Configuration
In the build.gradle.kts file, configure the Apollo-Kotlin plugin to handle multiple services:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("com.example.java-conventions")
kotlin("jvm") version "1.6.21"
kotlin("plugin.spring") version "1.6.21"
id("com.apollographql.apollo3") version "3.5.0"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
api("org.jetbrains.kotlin:kotlin-reflect")
api("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
api("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8")
api("com.apollographql.apollo3:apollo-runtime:3.5.0")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
apollo {
generateKotlinModels.set(false)
service("endpointA") {
srcDir("src/main/graphql/endpointA")
packageName.set("com.example.graphql.endpointA")
}
service("endpointB") {
srcDir("src/main/graphql/endpointB")
packageName.set("com.example.graphql.endpointB")
}
}
Apollo Client Configuration
Create a configuration class to define multiple ApolloClient instances for different endpoints:
@Configuration
class ApolloConfig {
@Bean
fun clientForEndpointA(): ApolloClient {
return ApolloClient.Builder()
.serverUrl("https://api.example1.com/graphql")
.build()
}
@Bean
fun clientForEndpointB(): ApolloClient {
return ApolloClient.Builder()
.serverUrl("https://api.example2.com/graphql")
.build()
}
}
Service Implementation
Implement a service class that injects and uses the configured ApolloClient instances:
@Service
class GraphQLService(
@Autowired private val clientA: ApolloClient,
@Autowired private val clientB: ApolloClient
) {
suspend fun fetchDataFromEndpointA(): String {
val query = EndpointAQuery()
val response = clientA.query(query).execute()
return response.data?.result ?: "No data"
}
suspend fun fetchDataFromEndpointB(): String {
val query = EndpointBQuery()
try {
val response = clientB.query(query).execute()
return response.data?.result ?: "No data"
} catch (e: ApolloException) {
return "Error: ${e.message}"
}
}
}
Schema Download Methods
Using Gradle Plugin
Execute the folloiwng commands to download schemas for each endpoint:
# For endpoint A
./gradlew downloadApolloSchema \
--endpoint="https://api.example1.com/graphql" \
--schema="src/main/graphql/endpointA/schema.graphqls"
# For endpoint B
./gradlew downloadApolloSchema \
--endpoint="https://api.example2.com/graphql" \
--schema="src/main/graphql/endpointB/schema.graphqls"
Using Apollo CLI
Install the Apollo CLI and download schemas:
npm install -g apollo
npm install -g graphql
# For endpoint A
apollo schema:download --endpoint=https://api.example1.com/graphql schema.json
# For endpoint B
apollo schema:download --endpoint=https://api.example2.com/graphql schema.json
Code Generation
The Gradle plugin includes a generateApolloSources task that automatically generates Kotlin models from GraphQL queries and schemas. This task runs during the project build process, placing generated code in the specified source directories.