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

ControllerAdvice order is not preserved in AnnotatedControllerExceptionResolver #830

Closed
yodono opened this issue Oct 2, 2023 · 3 comments
Assignees
Labels
in: web Issues related to web handling type: bug A general bug
Milestone

Comments

@yodono
Copy link

yodono commented Oct 2, 2023

Hello,

When you have many @ControllerAdvice classes, the @Order given to each bean is not respected.

I built a sample project demonstrating this behavior: https://github.com/yodono/spring-graphql-advice-order. Despite one of my classes having an @Order(Ordered.HIGHEST_PRECEDENCE) annotation, it does not run first.

It seems that AnnotatedControllerExceptionResolver is using a ConcurrentHashMap when registering beans in registerControllerAdvice. Later, when resolveException is called, the entries of this Map are iterated over but keeping no reference to the original order.

As a suggestion, there could be an extra call to OrderComparator before iterating over the controllerAdviceCache.

List<Map.Entry<ControllerAdviceBean, MethodResolver>>
    entryList = new ArrayList<>(this.controllerAdviceCache.entrySet());

entryList.sort(Map.Entry.comparingByKey(OrderComparator.INSTANCE));

for (Map.Entry<ControllerAdviceBean, MethodResolver> entry : entryList) {
    ControllerAdviceBean advice = entry.getKey();
    ...
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 2, 2023
@bclozel bclozel self-assigned this Oct 2, 2023
@bclozel bclozel added type: bug A general bug in: web Issues related to web handling and removed status: waiting-for-triage An issue we've not yet triaged labels Oct 2, 2023
@bclozel bclozel added this to the 1.2.4 milestone Oct 2, 2023
@bclozel bclozel closed this as completed in 6c15e09 Oct 2, 2023
@bclozel
Copy link
Member

bclozel commented Oct 2, 2023

Thanks @yodono for this report! The fix will be available in the 1.2.4-SNAPSHOT version in a few minutes.

@xmazu
Copy link

xmazu commented Feb 7, 2024

Hello @bclozel. Sorry for reopening but after this change I can't create multiple @ControlledAdvice classes without adding explicit @Order. Wwhen I'm trying to use ConcurrentHashMap again, it works.

Example from tests with additional advice (handler moved from controller)

        @SuppressWarnings("unused")
	@ControllerAdvice
	private static class TestControllerAdvice {
		@GraphQlExceptionHandler
		GraphQLError handle(IllegalArgumentException ex) {
			return GraphQLError.newError().message("handle: " + ex.getMessage()).build();
		}

	}

	@ControllerAdvice
	private static class AnotherAdvice {
		@GraphQlExceptionHandler
		GraphQLError handleToObject(ClassCastException ex) {
			return GraphQLError.newError().message("handle: " + ex.getMessage()).build();
		}

	}


	@SuppressWarnings("unused")
	@ControllerAdvice
	private static class OrderedTestControllerAdvice {
		@GraphQlExceptionHandler
		GraphQLError handle(IllegalArgumentException ex) {
			return GraphQLError.newError().message("ordered handle: " + ex.getMessage()).build();
		}

	}

@bclozel
Copy link
Member

bclozel commented Feb 7, 2024

I don't understand. Can you create a new issue and share a sample application that demonstrates the problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues related to web handling type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants