dave08
11/14/2022, 4:43 PMDariusz Kuc
11/14/2022, 4:58 PMdave08
11/14/2022, 5:01 PMDariusz Kuc
11/14/2022, 5:01 PMSergey Shumov
11/14/2022, 6:39 PMdave08
11/15/2022, 10:01 AMdave08
11/15/2022, 10:11 AM@IntoSet
of a DI...dave08
11/15/2022, 10:13 AMSergey Shumov
11/15/2022, 10:30 AMconfugureDI
may be looks like:
fun Application.configureDI(testing: Boolean = false) {
di {
bindSingleton {
if (testing) {
new(::ArticleRepositoryMocked)
} else {
new(::ArticleRepository)
}
}
bindSingleton { new(::UserRepository) }
}
}
And test:
fun testModule1() = testApplication {
application {
configureDI(testing = true)
configureGraphQLModule()
}
}
Or using other ways of replacing dependencies that the DI library provides.dave08
11/15/2022, 10:32 AMSergey Shumov
11/15/2022, 10:43 AMdave08
11/15/2022, 11:30 AMdave08
11/15/2022, 11:31 AMSergey Shumov
11/15/2022, 11:40 AMSergey Shumov
11/15/2022, 11:46 AMclass ArticleQuery(
private val repository: ArticleRepository,
) : Query {
@GraphQLDescription("List of articles")
fun articles(
sortOrder: SortOrder? = null,
limit: Int? = null,
): List<ArticleDto> {
return repository.list(
sortOrder = sortOrder ?: SortOrder.DESC,
limit = limit,
)
}
}
When you declare a GraphQL schema, you can pass a repository from DI:
queries = listOf(ArticleQuery(articleRepository))
Similarly for mutations and dataloaders.dave08
11/15/2022, 11:49 AM@GraphQLName("Article")
@GraphQLDescription("Article")
data class ArticleDto(
val id: Long,
val created: OffsetDateTime,
val authorId: Long,
val title: String,
val content: String,
) {
fun author(dfe: DataFetchingEnvironment): CompletableFuture<User> {
return dfe.getValueFromDataLoader(UserDataLoader::class, authorId)
}
}
The dfe way is messier than:
@GraphQLName("Article")
@GraphQLDescription("Article")
data class ArticleDto(
val id: Long,
val created: OffsetDateTime,
val authorId: Long,
val title: String,
val content: String,
) {
fun author(authorRepo: AuthorRepository): CompletableFuture<User> {
return authorRepo.getAuthor(id)
}
}
Also, it requires making a data loader for each thing...Dariusz Kuc
11/15/2022, 4:14 PMDariusz Kuc
11/15/2022, 4:14 PMCore schema generation logic only concern is with GraphQL and DI is outside of its scope of responsibilities. DI is higher level concept that is handled by your specific server implementation.
Our graphql-kotlin-spring-server library is a SpringBoot autoconfiguration library to easily run reactive GraphQL servers. Since it is SpringBoot based, it does support Spring DI mechanism (see <https://opensource.expediagroup.com/graphql-kotlin/docs/server/spring-server/spring-schema/>).
If you are looking at servers outside of Spring, then you can use whatever mechanism they support, e.g. see Ktor + Koin example (<https://insert-koin.io/docs/reference/koin-ktor/ktor>).
Side note: data loaders should always be accessed through DataFetchingEnvironment (as they are created per execution) and generally should not be injected directly to your classes