smallrye-graphql: Add ability for users to add error code
Hello there,
I’m a new person to GraphQL but in the last few days I was experimenting with it within the Quarkus framework, and I’m liking it so far. When it comes to writing code sometimes error can occur and I like to specify the error via error codes or with reasons which are straightforward and can be consumed easily by the caller. In the official GraphQL specification there are a few section about errors and one of them is specifying how the programmers could define “custom” error codes in their responses. Take a look at here: https://spec.graphql.org/June2018/#example-fce18
So what I see there if the programmer would like to indicate any kind of custom behavior in the error response they just have to put this information into the extension section in a key-value format. Easy.
The problem with that in the SmallRye implementation this kind of stuff is not working properly (yet).
An example: I have a GraphQL API like the following:
@GraphQLApi
public class PackageResource {
@Query("getPackages")
@Description("Returns all available packages")
public List<Package> getPackages() {
throw GraphqlErrorException.newErrorException()
.message("Something went wrong")
.extensions(Map.of("code","CUSTOM_ERROR_CODE"))
.build();
}
}
I found the GraphqlErrorException class and it looks fine, because it has an extensions variable in it and it can be populated, so far so good, btw this class is coming from the com.graphql-java:graphql-java:14.0 dependency right now.
So when this exception is being thrown it will be handled by the io.smallrye.graphql.execution.error.ExceptionHandler where it will be wrapped as a io.smallrye.graphql.execution.error.GraphQLExceptionWhileDataFetching exception which calls it’s super class constructor graphql.ExceptionWhileDataFetching and it sets any kind of incoming extensions in it.
public ExceptionWhileDataFetching(ExecutionPath path, Throwable exception, SourceLocation sourceLocation) {
this.path = assertNotNull(path).toList();
this.exception = assertNotNull(exception);
this.locations = Collections.singletonList(sourceLocation);
this.extensions = mkExtensions(exception);
this.message = mkMessage(path, exception);
}
At this point if a newly created exception is containing extra extensions then it will be populated there. The problems comes when this exception is being serialized by the io.smallrye.graphql.execution.error.ExecutionErrorsService#toJsonError method.
It basically “replaces” or just simply ignores the content of the extensions field.
io.smallrye.graphql.execution.error.ExecutionErrorsService#getDataFetchingExtensions
private Optional<JsonObject> getDataFetchingExtensions(ExceptionWhileDataFetching error) {
Throwable exception = error.getException();
JsonObjectBuilder objectBuilder = jsonBuilderFactory.createObjectBuilder();
addKeyValue(objectBuilder, EXCEPTION, exception.getClass().getName());
addKeyValue(objectBuilder, CLASSIFICATION, error.getErrorType().toString());
return Optional.of(objectBuilder.build());
}
So my question is the following, is there any way to populate the response with the values in the extensions field within the ExceptionWhileDataFetching exception?
If there is no specific reason for ignoring the custom values then I think a change could be made to the getDataFetchingExtensions method, if there is a specific reason for ignoring them, then please ignore this issue ticket 😃
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (12 by maintainers)
Commits related to this issue
- #282 - Add ability for users to add error code and other extensions - Populating extensions based on the caught GraphqlErrorException — committed to nandorholozsnyak/smallrye-graphql by nandorholozsnyak 4 years ago
- #282 - Add ability for users to add error code and other extensions - Objects.nonNull replaced with != - Unit tests for ExecutionErrorsService — committed to nandorholozsnyak/smallrye-graphql by nandorholozsnyak 4 years ago
- #282 - Add ability for users to add error code and other extensions - Formatting and import fixes — committed to nandorholozsnyak/smallrye-graphql by nandorholozsnyak 4 years ago
- Merge pull request #284 from nandorholozsnyak/feature/#282-add-error-code-and-other-extensions #282 - Add ability for users to add error code and other extensions — committed to smallrye/smallrye-graphql by phillip-kruger 4 years ago
- #282: get error extension `code` from exception name or annotation — committed to t1/smallrye-graphql by t1 4 years ago
- #282: add tck tests — committed to t1/smallrye-graphql by t1 4 years ago
- #282: PR feedback — committed to t1/smallrye-graphql by t1 4 years ago
- Merge pull request #295 from t1/#282-error-code-annotation #282: get error extension `code` from exception name or annotation — committed to smallrye/smallrye-graphql by phillip-kruger 4 years ago
This is now partially fix, I create another ticket for the outstanding (see #299)
I’ll work on supporting
@GraphQlErrorCodenow.Awesome idea! I would like to go even a step further: there would be a big benefit, if there was a standard extension field for error codes. If
codeis the name of that extension commonly used in the GraphQL community, we should make it as easy as by any means possible to set in MP GraphQL:The code could be derived directly from the simple class name!
If that is not what we want, we could specify the code explicitly:
… or on a method if it needs to be dynamic:
… or on a field:
Any type could be used (esp. an enum), and it would be mapped to a string. I think it would only be extra work for clients to sometimes have other types, e.g. a numeric 404 in some cases… let’s stick to string.
On the client side, it would be ideal if the error code would be mapped back to an exception, but there are a number of open questions. We should discuss this in #167.
For REST services there’s a standard rfc-7807 that uses
typeinstead ofcode, but it means the same thing: a permanent code to identify the type of error. They suggest to use an URI for the error type, so we could use a URL to the documentation of the code. But that’s RESTful thinking 😉 It’s actually not easy to have absolutely stable URLs, so it may be better to have a separate URL extension field for the documentation URL; it’s a separate concern after all.There are other very useful things specified in rfc-7807 that we could use as well, but the
codeis by far the most important one. Let’s start with that and continue from there.Hi @nandorholozsnyak . Thanks for the detailed issue ! So I think there is two issues here:
Both of these issues should be handled in the spec, but we can fix it here in the mean time.