Skip to content

Commit c0e6d56

Browse files
committed
Polishing.
Moves the ordering from the security access exception handler class to the bean definition in the `SecurityAutoConfiguration`. Adds an auto-configuration test to ensure user-defined exception handlers can be ordered around the security exception handler. Adds an auto-configuration test to ensure user-defined exception handlers can be ordered in general. Original Pull Request #371 Signed-off-by: onobc <chris.bono@gmail.com>
1 parent 22b38ce commit c0e6d56

4 files changed

Lines changed: 86 additions & 16 deletions

File tree

spring-grpc-core/src/main/java/org/springframework/grpc/server/security/SecurityGrpcExceptionHandler.java

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,22 @@
2020
import org.apache.commons.logging.LogFactory;
2121
import org.jspecify.annotations.Nullable;
2222

23-
import org.springframework.core.Ordered;
2423
import org.springframework.grpc.server.exception.GrpcExceptionHandler;
2524
import org.springframework.security.access.AccessDeniedException;
2625
import org.springframework.security.core.AuthenticationException;
2726

2827
import io.grpc.Status;
2928
import io.grpc.StatusException;
3029

31-
public class SecurityGrpcExceptionHandler implements GrpcExceptionHandler, Ordered {
30+
/**
31+
* Exception handler for server-side exceptions.
32+
*
33+
* @author Dave Syer
34+
*/
35+
public class SecurityGrpcExceptionHandler implements GrpcExceptionHandler {
3236

3337
private static final Log logger = LogFactory.getLog(SecurityGrpcExceptionHandler.class);
3438

35-
private final int order;
36-
37-
public SecurityGrpcExceptionHandler(int order) {
38-
this.order = order;
39-
}
40-
4139
@Override
4240
public @Nullable StatusException handleException(Throwable exception) {
4341
if (exception instanceof AuthenticationException) {
@@ -55,9 +53,4 @@ public SecurityGrpcExceptionHandler(int order) {
5553
return null;
5654
}
5755

58-
@Override
59-
public int getOrder() {
60-
return this.order;
61-
}
62-
6356
}

spring-grpc-server-spring-boot-autoconfigure/src/main/java/org/springframework/boot/grpc/server/autoconfigure/security/GrpcSecurityAutoConfiguration.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.context.annotation.Bean;
3535
import org.springframework.context.annotation.Configuration;
3636
import org.springframework.context.annotation.Import;
37+
import org.springframework.core.annotation.Order;
3738
import org.springframework.grpc.server.GlobalServerInterceptor;
3839
import org.springframework.grpc.server.exception.GrpcExceptionHandler;
3940
import org.springframework.grpc.server.security.CoroutineSecurityContextInterceptor;
@@ -55,6 +56,7 @@
5556
* @author Dave Syer
5657
* @author Chris Bono
5758
* @author Andrey Litvitski
59+
* @author Thomas Skjolberg
5860
* @since 1.0.0
5961
*/
6062
@AutoConfiguration(before = GrpcExceptionHandlerAutoConfiguration.class,
@@ -71,8 +73,9 @@ public final class GrpcSecurityAutoConfiguration {
7173
static class ExceptionHandlerConfiguration {
7274

7375
@Bean
76+
@Order(0)
7477
GrpcExceptionHandler accessExceptionHandler() {
75-
return new SecurityGrpcExceptionHandler(0);
78+
return new SecurityGrpcExceptionHandler();
7679
}
7780

7881
}

spring-grpc-server-spring-boot-autoconfigure/src/test/java/org/springframework/boot/grpc/server/autoconfigure/exception/GrpcExceptionHandlerAutoConfigurationTests.java

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.grpc.server.autoconfigure.exception;
1818

1919
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.mockito.Mockito.mock;
2021

2122
import org.assertj.core.api.InstanceOfAssertFactories;
2223
import org.junit.jupiter.api.Test;
@@ -25,7 +26,11 @@
2526
import org.springframework.boot.autoconfigure.AutoConfigurations;
2627
import org.springframework.boot.test.context.FilteredClassLoader;
2728
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
29+
import org.springframework.context.annotation.Bean;
30+
import org.springframework.context.annotation.Configuration;
31+
import org.springframework.core.annotation.Order;
2832
import org.springframework.grpc.server.GrpcServerFactory;
33+
import org.springframework.grpc.server.exception.CompositeGrpcExceptionHandler;
2934
import org.springframework.grpc.server.exception.GrpcExceptionHandler;
3035
import org.springframework.grpc.server.exception.GrpcExceptionHandlerInterceptor;
3136
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
@@ -121,9 +126,43 @@ void whenHasUserDefinedGrpcExceptionHandlerInterceptorDoesNotAutoConfigureBean()
121126
void exceptionHandlerInterceptorAutoConfiguredAsExpected() {
122127
this.contextRunner()
123128
.run((context) -> assertThat(context).getBean(GrpcExceptionHandlerInterceptor.class)
124-
.extracting("exceptionHandler.exceptionHandlers",
125-
InstanceOfAssertFactories.array(GrpcExceptionHandler[].class))
129+
.extracting("exceptionHandler")
130+
.isInstanceOf(CompositeGrpcExceptionHandler.class)
131+
.extracting("exceptionHandlers")
132+
.asInstanceOf(InstanceOfAssertFactories.array(GrpcExceptionHandler[].class))
126133
.containsExactly(context.getBean(GrpcExceptionHandler.class)));
127134
}
128135

136+
@Test
137+
void userDefinedExceptionHandlersCanBeOrdered() {
138+
this.contextRunner()
139+
.withUserConfiguration(UserExceptionHandlerConfig.class)
140+
.run((context) -> assertThat(context).getBean(GrpcExceptionHandlerInterceptor.class)
141+
.extracting("exceptionHandler.exceptionHandlers")
142+
.asInstanceOf(InstanceOfAssertFactories.array(GrpcExceptionHandler[].class))
143+
.startsWith(UserExceptionHandlerConfig.USER_EXCEPTION_HANDLER_BAR,
144+
UserExceptionHandlerConfig.USER_EXCEPTION_HANDLER_FOO));
145+
}
146+
147+
@Configuration(proxyBeanMethods = false)
148+
static class UserExceptionHandlerConfig {
149+
150+
static GrpcExceptionHandler USER_EXCEPTION_HANDLER_FOO = mock();
151+
152+
static GrpcExceptionHandler USER_EXCEPTION_HANDLER_BAR = mock();
153+
154+
@Bean
155+
@Order(200)
156+
GrpcExceptionHandler userExceptionHandlerFoo() {
157+
return USER_EXCEPTION_HANDLER_FOO;
158+
}
159+
160+
@Bean
161+
@Order(100)
162+
GrpcExceptionHandler userExceptionHandlerBar() {
163+
return USER_EXCEPTION_HANDLER_BAR;
164+
}
165+
166+
}
167+
129168
}

spring-grpc-server-spring-boot-autoconfigure/src/test/java/org/springframework/boot/grpc/server/autoconfigure/security/GrpcSecurityAutoConfigurationTests.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.grpc.server.autoconfigure.security;
1818

1919
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.mockito.Mockito.mock;
2021

2122
import org.junit.jupiter.api.Test;
2223
import org.mockito.Mockito;
@@ -27,7 +28,9 @@
2728
import org.springframework.boot.logging.LogLevel;
2829
import org.springframework.boot.test.context.FilteredClassLoader;
2930
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
31+
import org.springframework.context.annotation.Bean;
3032
import org.springframework.context.annotation.Configuration;
33+
import org.springframework.core.annotation.Order;
3134
import org.springframework.grpc.server.GrpcServerFactory;
3235
import org.springframework.grpc.server.exception.GrpcExceptionHandler;
3336
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
@@ -110,10 +113,42 @@ void grpcSecurityAutoConfiguredAsExpected() {
110113
});
111114
}
112115

116+
@Test
117+
void userDefinedExceptionHandlerCanBeOrderedAroundSecurityExceptionHandler() {
118+
this.contextRunner().withUserConfiguration(UserExceptionHandlerConfig.class).run((context) -> {
119+
GrpcExceptionHandler securityExceptionHandler = context.getBean("accessExceptionHandler",
120+
SecurityGrpcExceptionHandler.class);
121+
assertThat(context.getBeanProvider(GrpcExceptionHandler.class).orderedStream()).containsExactly(
122+
UserExceptionHandlerConfig.USER_HANDLER_PRE_SECURITY_HANDLER, securityExceptionHandler,
123+
UserExceptionHandlerConfig.USER_HANDLER_POST_SECURITY_HANDLER);
124+
});
125+
}
126+
113127
@EnableMethodSecurity
114128
@Configuration(proxyBeanMethods = false)
115129
static class ExtraConfiguration {
116130

117131
}
118132

133+
@Configuration(proxyBeanMethods = false)
134+
static class UserExceptionHandlerConfig {
135+
136+
static GrpcExceptionHandler USER_HANDLER_PRE_SECURITY_HANDLER = mock();
137+
138+
static GrpcExceptionHandler USER_HANDLER_POST_SECURITY_HANDLER = mock();
139+
140+
@Bean
141+
@Order(-10)
142+
GrpcExceptionHandler userHandlerPreSecurityHandler() {
143+
return USER_HANDLER_PRE_SECURITY_HANDLER;
144+
}
145+
146+
@Bean
147+
@Order(10)
148+
GrpcExceptionHandler userHandlerPostSecurityHandler() {
149+
return USER_HANDLER_POST_SECURITY_HANDLER;
150+
}
151+
152+
}
153+
119154
}

0 commit comments

Comments
 (0)