graphql-spring-boot icon indicating copy to clipboard operation
graphql-spring-boot copied to clipboard

Custom exception handlers are not detected when using Spring Cloud Stream

Open nictas opened this issue 3 years ago • 2 comments

Describe the bug Custom exception handlers are not detected whenever Spring Cloud Stream with the Solace PubSub+ binder is on the classpath.

Let's say we have two custom exceptions, Foo and Bar, along with the following exception handler:

@Component
public class GraphQLExceptionHandler {

    @ExceptionHandler(Foo.class)
    public ThrowableGraphQLError handle(Foo e) {
        return new ThrowableGraphQLError(e);
    }

    @ExceptionHandler(Throwable.class)
    public ThrowableGraphQLError handle(Throwable e) {
        return new ThrowableGraphQLError(e, "Internal Server Error(s) while executing query");
    }

}

Exceptions of type Foo should then have their messages displayed to the user directly, but any other exception type should be hidden behind a generic error message before being shown to the user. This works fine, until the following two dependencies are added to the project:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>com.solace.spring.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-solace</artifactId>
        </dependency>

After a lot of debugging I've been able to find one clue as to what's going wrong. The ApplicationContext instance that gets passed to com.nictas.graphql.curious.dolphin.graphql.GraphQLExceptionHandler is different depending on whether the Maven dependencies mentioned above are on the classpath or not:

  • org.springframework.context.annotation.AnnotationConfigApplicationContext if they are; An important thing to note is that the AnnotationConfigApplicationContext instance does NOT contain the custom exception handler bean (hence the issue). That's because the bean is in a different application context (the AnnotationConfigServletWebServerApplicationContext instance that still exists). The problem seems to come from the fact that a second application context is created whenever Spring Cloud Stream is on the classpath and the GraphQLExceptionHandler is called with the wrong one.
  • org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext if they are NOT;

I've tried using the latest versions of Spring and GraphQL kickstart, but nothing solves the issue.

To Reproduce I've created a small project that can be used to reproduce the problem: https://github.com/nictas/graphql-curious-dolphin Just follow the instructions in its README.

Desktop:

  • OS: Windows 10
  • Browser: Google Chrome
  • Version: 90.0.4430.212 (Official Build) (64-bit)

nictas avatar May 24 '21 14:05 nictas

@nictas does your application.yaml contain following configuration?

graphql:
  servlet:
    exception-handlers-enabled: true

I had same issue after upgrading to 11.1.0 and adding exception-handlers-enabled: true helped me

bbellovic avatar May 30 '21 11:05 bbellovic

@bBellovic It does, yes: https://github.com/nictas/graphql-curious-dolphin/blob/eaf9b18b34037d051b121f06f451c9002649e276/src/main/resources/application.yaml#L6

nictas avatar Jun 29 '21 06:06 nictas