Migrating to Apollo Kotlin 5
Step-by-step guide on migrating from Apollo Kotlin 4
Apollo Kotlin 5 is mostly binary compatible with Apollo Kotlin 4 with a few exceptions:
Symbols that were
DeprecationLevel.ERROR
in v4 are now removed.apollo-compiler
has breaking changes and is generally still considered unstable with the exception of persisted queries compiler plugins:ApolloCompilerPlugin.beforeCompilationStep()
,ApolloCompilerRegistry.registerOperationIdsGenerator()
and dependent symbols are stable and will go through the usual deprecation cycle if they ever need to change.
The APIs used by the data builders generated sources (
buildData
,ObjectBuilder
,CustomScalarAdapters.PASSTHROUGH
...) have changed. This is not an issue unless you called those APIs directly or distributed data builders code in a library. In that last case, your consumers will have to update to Apollo Kotlin 5.A few symbols were not supposed to be exposed and have been hidden:
BooleanExpression.simplify()
DefaultHttpRequestComposer.HEADER_APOLLO_OPERATION_ID
...
We tried hard to minimize the impact of the binary changes so that running code compiled for v4 will run with v5. But the occasional incompatibility may happen. In that case, the incompatible libraries will need to compile against v5 and make a new release.
Removed Service.operationOutputGenerator
and Service.operationIdGenerator
While running your OperationOutputGenerator
directly in your build script classpath was convenient, it required the compiler code to run completely in the global buildscript classpath. This created numerous issues such as incompatible dependencies and/or unneeded build invalidations.
To mitigate the impact of incompatible dependencies, Apollo Kotlin 4 used to shadow and relocate all its dependencies, which came with additional issues: increased build times, weird stack traces and larger plugin size.
Apollo Kotlin v5 instead runs its compiler in isolated classloaders, meaning generating the ids now needs to happen in that same classloader.
To do so, use ApolloCompilerPlugin
:
1class MyPlugin : ApolloCompilerPlugin {
2 override fun beforeCompilationStep(
3 environment: ApolloCompilerPluginEnvironment,
4 registry: ApolloCompilerRegistry,
5 ) {
6 registry.registerOperationIdsGenerator {
7 it.map { OperationId(it.source.md5(), it.name) }
8 }
9 }
10}
Read more in the persisted queries and compiler plugins pages.
Removed ApolloIdlingResource
Apollo Kotlin 5 removes ApolloIdlingResource
. IdlingResource
usage has been slowly decreasing and there are now better alternatives to do your testing.
For a good overview of alternative solutions, we recommend this article from Jose Alcérreca.
Using @nonnull
is now an error
Apollo Kotlin 4 had a @nonnull
client directive to force generating fields as non-null.
Since @nonnull
, we've worked hard with the nullability working group to improve the handling of null types in GraphQL.
As part of this effort, it was recognized that the nullability information belongs to the schema. Fields that are only nullable for error reasons can now be marked with @semanticNonNull
:
1type User {
2 email: String @semanticNonNull
3}
4
5# or if you don't own the schema, use extensions
6extend type User @semanticNonNullField(name: "email")
The client can then decide how to handle errors with @catch
:
1query GetUser {
2 user {
3 # generated as `String?` (current default)
4 email @catch(to: NULL)
5 # generated as `Result<String, Error>`
6 email @catch(to: RESULT)
7 # generated as `String`, throws if there is an error
8 email @catch(to: THROW)
9 }
10}
You can read more in the "handling nullability" page.