Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move ApolloParseException to ApolloNetworkException #5816

Merged
merged 1 commit into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libraries/apollo-api/api/apollo-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,10 @@ public final class com/apollographql/apollo3/exception/NoDataException : com/apo
public fun <init> (Ljava/lang/Throwable;)V
}

public final class com/apollographql/apollo3/exception/NullOrMissingField : com/apollographql/apollo3/exception/ApolloException {
public fun <init> (Ljava/lang/String;)V
}

public final class com/apollographql/apollo3/exception/RouterError : com/apollographql/apollo3/exception/ApolloException {
public fun <init> (Ljava/util/List;)V
public final fun getErrors ()Ljava/util/List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package com.apollographql.apollo3.api

import com.apollographql.apollo3.api.json.JsonReader
import com.apollographql.apollo3.exception.DefaultApolloException
import com.apollographql.apollo3.exception.NullOrMissingField
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName

Expand All @@ -13,7 +13,7 @@ import kotlin.jvm.JvmName
*/
fun checkFieldNotMissing(value: Any?, name: String) {
if (value == null) {
throw DefaultApolloException("Field '$name' is missing or null")
throw NullOrMissingField("Field '$name' is missing or null")
}
}

Expand All @@ -35,5 +35,5 @@ fun assertOneOf(vararg args: Optional<*>) {
* Helper function for the Kotlin codegen
*/
fun missingField(jsonReader: JsonReader, name: String): Nothing {
throw DefaultApolloException("Field '$name' is missing or null at path ${jsonReader.getPath()}")
throw NullOrMissingField("Field '$name' is missing or null at path ${jsonReader.getPath()}")
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.apollographql.apollo3.api.json.JsonReader
import com.apollographql.apollo3.api.json.JsonWriter
import com.apollographql.apollo3.api.json.writeObject
import com.apollographql.apollo3.exception.ApolloException
import com.apollographql.apollo3.exception.ApolloParseException
import com.apollographql.apollo3.exception.ApolloNetworkException
import com.apollographql.apollo3.exception.JsonDataException
import com.apollographql.apollo3.exception.JsonEncodingException
import com.benasher44.uuid.Uuid
Expand Down Expand Up @@ -114,10 +114,9 @@ fun <D : Operation.Data> Operation<D>.parseResponse(
val apolloException = if (throwable is ApolloException) {
throwable
} else {
// This happens for null pointer exceptions on missing fields
ApolloParseException(
message = "Failed to parse GraphQL http network response",
cause = throwable
ApolloNetworkException(
message = "Error while reading JSON response",
platformCause = throwable
)
}
return ApolloResponse.Builder(requestUuid = requestUuid ?: uuid4(), operation = this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import okio.BufferedSource
sealed class ApolloException(message: String? = null, cause: Throwable? = null) : RuntimeException(message, cause)

/**
* A generic exception when no additional context exists
* A generic exception used when there is no additional context besides the message.
*/
class DefaultApolloException(message: String? = null, cause: Throwable? = null): ApolloException(message, cause)

Expand All @@ -25,7 +25,10 @@ class DefaultApolloException(message: String? = null, cause: Throwable? = null):
class NoDataException(cause: Throwable?): ApolloException("No data was found", cause)

/**
* A network error happened: socket closed, DNS issue, TLS problem, etc...
* An I/O error happened: socket closed, DNS issue, TLS problem, file not found, etc...
*
* This is called [ApolloNetworkException] for historical reasons, but it should have been `ApolloIOException` instead.
* [ApolloNetworkException] is thrown when an I/O error happens reading the operation.
*
* @param message a message indicating what the error was.
* @param platformCause the underlying cause. Might be null. When not null, it can be cast to:
Expand Down Expand Up @@ -58,7 +61,6 @@ class SubscriptionConnectionException(
val payload: Any?,
) : ApolloException(message = "Subscription connection error")


/**
* The router sent one or several errors.
*
Expand Down Expand Up @@ -108,15 +110,26 @@ class JsonEncodingException(message: String) : ApolloException(message)
*
* Exceptions of this type should be fixed by either changing the application code to accept the unexpected JSON, or by changing the JSON
* to conform to the application's expectations.
*
* This exception may also be triggered if a document's nesting exceeds 31 levels. This depth is sufficient for all practical applications,
* but shallow enough to avoid uglier failures like [StackOverflowError].
*/
class JsonDataException(message: String) : ApolloException(message)

/**
* The response could not be parsed either because of another issue than [JsonDataException] or [JsonEncodingException]
* A field was missing or null in the JSON response.
*
* Due to the way the parsers work, it is not possible to distinguish between both cases.
*/
class NullOrMissingField(message: String): ApolloException(message)

/**
* The response could not be parsed because of an I/O exception.
*
* JSON and GraphQL errors are throwing other errors, see [JsonEncodingException], [JsonDataException] and [NullOrMissingField]
*
* @see JsonEncodingException
* @see JsonDataException
* @see NullOrMissingField
*/
@Deprecated("ApolloParseException was only used for I/O exceptions and is now mapped to ApolloNetworkException.")
class ApolloParseException(message: String? = null, cause: Throwable? = null) : ApolloException(message = message, cause = cause)

class ApolloGraphQLException(val error: Error): ApolloException("GraphQL error: '${error.message}'") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public <D extends Operation.Data> void execute(@NotNull ApolloRequest<D> request
}

@Override public void onFailure(@NotNull ApolloNetworkException exception) {
callback.onResponse(getExceptionResponse(request, new ApolloParseException("Cannot parse response", exception)));
callback.onResponse(getExceptionResponse(request, exception));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import com.apollographql.apollo3.api.parseResponse
import com.apollographql.apollo3.api.toApolloResponse
import com.apollographql.apollo3.exception.ApolloException
import com.apollographql.apollo3.exception.ApolloHttpException
import com.apollographql.apollo3.exception.ApolloParseException
import com.apollographql.apollo3.exception.ApolloNetworkException
import com.apollographql.apollo3.exception.RouterError
import com.apollographql.apollo3.internal.DeferredJsonMerger
import com.apollographql.apollo3.internal.isMultipart
Expand Down Expand Up @@ -104,10 +104,9 @@ private constructor(
val apolloException = if (throwable is ApolloException) {
throwable
} else {
// This happens for null pointer exceptions on missing fields
ApolloParseException(
message = "Failed to parse GraphQL http network response",
cause = throwable
ApolloNetworkException(
message = "Error while reading JSON response",
platformCause = throwable
)
}
return ApolloResponse.Builder(requestUuid = uuid4(), operation = operation)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package test

import com.apollographql.apollo3.exception.DefaultApolloException
import com.apollographql.apollo3.exception.NullOrMissingField
import data.builders.fragment.AnimalDetailsImpl
import data.builders.fragment.CatDetailsImpl
import data.builders.fragment.TrivialFragmentImpl
Expand Down Expand Up @@ -43,7 +43,7 @@ class FragmentTest {
// __typename is unknown so this fails
// XXX: we could be smarter about this (the parsers are
// data.builders.fragment.AnimalDetailsImpl_ResponseAdapter$OnAnimal.fromJson(AnimalDetailsImpl_ResponseAdapter.kt:85)
assertFailsWith(DefaultApolloException::class) {
assertFailsWith(NullOrMissingField::class) {
TrivialFragmentImpl.Data(Animal) {
__typename = "Brontaroc"
species = "alien"
Expand Down
9 changes: 5 additions & 4 deletions tests/http-cache/src/test/kotlin/HttpCacheTest.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@

import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.cache.http.HttpFetchPolicy
import com.apollographql.apollo3.cache.http.httpCache
import com.apollographql.apollo3.cache.http.httpExpireTimeout
import com.apollographql.apollo3.cache.http.httpFetchPolicy
import com.apollographql.apollo3.cache.http.isFromHttpCache
import com.apollographql.apollo3.exception.ApolloParseException
import com.apollographql.apollo3.exception.ApolloNetworkException
import com.apollographql.apollo3.exception.HttpCacheMissException
import com.apollographql.apollo3.mockserver.MockServer
import com.apollographql.apollo3.mockserver.awaitRequest
Expand Down Expand Up @@ -212,9 +213,9 @@ class HttpCacheTest {
@Test
fun incompleteJsonIsNotCached() = runTest(before = { before() }, after = { tearDown() }) {
mockServer.enqueueString("""{"data":""")
assertIs<ApolloParseException>(
apolloClient.query(GetRandomQuery()).execute().exception
)
apolloClient.query(GetRandomQuery()).execute().exception.apply {
assertIs<ApolloNetworkException>(this)
}
// Should not have been cached
assertIs<HttpCacheMissException>(
apolloClient.query(GetRandomQuery()).httpFetchPolicy(HttpFetchPolicy.CacheOnly).execute().exception
Expand Down
Loading