Skip to content

Commit 2ba1c55

Browse files
committed
add ability to filter out services from being bound to server factories (#207)
Signed-off-by: Andrey Litvitski <[email protected]>
1 parent 7dd7cbd commit 2ba1c55

File tree

6 files changed

+103
-11
lines changed

6 files changed

+103
-11
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,21 @@ public class DefaultGrpcServerFactory<T extends ServerBuilder<T>> implements Grp
6868

6969
private ClientAuth clientAuth;
7070

71+
private ServerServiceDefinitionFilter serviceFilter;
72+
7173
public DefaultGrpcServerFactory(String address, List<ServerBuilderCustomizer<T>> serverBuilderCustomizers) {
7274
this.address = address;
7375
this.serverBuilderCustomizers = Objects.requireNonNull(serverBuilderCustomizers, "serverBuilderCustomizers");
7476
}
7577

7678
public DefaultGrpcServerFactory(String address, List<ServerBuilderCustomizer<T>> serverBuilderCustomizers,
77-
KeyManagerFactory keyManager, TrustManagerFactory trustManager, ClientAuth clientAuth) {
79+
KeyManagerFactory keyManager, TrustManagerFactory trustManager, ClientAuth clientAuth,
80+
ServerServiceDefinitionFilter serviceFilter) {
7881
this(address, serverBuilderCustomizers);
7982
this.keyManager = keyManager;
8083
this.trustManager = trustManager;
8184
this.clientAuth = clientAuth;
85+
this.serviceFilter = serviceFilter;
8286
}
8387

8488
protected String address() {
@@ -94,7 +98,9 @@ public Server createServer() {
9498

9599
@Override
96100
public void addService(ServerServiceDefinition service) {
97-
this.serviceList.add(service);
101+
if (this.serviceFilter == null || this.serviceFilter.filter(service, this)) {
102+
this.serviceList.add(service);
103+
}
98104
}
99105

100106
/**

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public class NettyGrpcServerFactory extends DefaultGrpcServerFactory<NettyServer
3737

3838
public NettyGrpcServerFactory(String address,
3939
List<ServerBuilderCustomizer<NettyServerBuilder>> serverBuilderCustomizers, KeyManagerFactory keyManager,
40-
TrustManagerFactory trustManager, ClientAuth clientAuth) {
41-
super(address, serverBuilderCustomizers, keyManager, trustManager, clientAuth);
40+
TrustManagerFactory trustManager, ClientAuth clientAuth, ServerServiceDefinitionFilter serviceFilter) {
41+
super(address, serverBuilderCustomizers, keyManager, trustManager, clientAuth, serviceFilter);
4242
}
4343

4444
@Override
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2023-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.grpc.server;
17+
18+
import io.grpc.ServerServiceDefinition;
19+
20+
/**
21+
* Strategy to determine whether a {@link ServerServiceDefinition} should be included for
22+
* a given {@link GrpcServerFactory server factory}.
23+
*
24+
* @author Andrey Litvitski
25+
*/
26+
@FunctionalInterface
27+
public interface ServerServiceDefinitionFilter {
28+
29+
/**
30+
* Determine whether the given {@link ServerServiceDefinition} should be included for
31+
* the provided {@link GrpcServerFactory server factory}.
32+
* @param serviceDefinition the gRPC service definition under consideration.
33+
* @param serverFactory the server factory in use.
34+
* @return {@code true} if the service should be included; {@code false} otherwise.
35+
*/
36+
boolean filter(ServerServiceDefinition serviceDefinition, GrpcServerFactory serverFactory);
37+
38+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public class ShadedNettyGrpcServerFactory extends DefaultGrpcServerFactory<Netty
3737

3838
public ShadedNettyGrpcServerFactory(String address,
3939
List<ServerBuilderCustomizer<NettyServerBuilder>> serverBuilderCustomizers, KeyManagerFactory keyManager,
40-
TrustManagerFactory trustManager, ClientAuth clientAuth) {
41-
super(address, serverBuilderCustomizers, keyManager, trustManager, clientAuth);
40+
TrustManagerFactory trustManager, ClientAuth clientAuth, ServerServiceDefinitionFilter serviceFilter) {
41+
super(address, serverBuilderCustomizers, keyManager, trustManager, clientAuth, serviceFilter);
4242
}
4343

4444
@Override

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

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

1919
import java.util.List;
20+
import java.util.Optional;
2021

2122
import javax.net.ssl.KeyManagerFactory;
2223
import javax.net.ssl.TrustManagerFactory;
@@ -36,6 +37,7 @@
3637
import org.springframework.grpc.server.NettyGrpcServerFactory;
3738
import org.springframework.grpc.server.ServerBuilderCustomizer;
3839
import org.springframework.grpc.server.ShadedNettyGrpcServerFactory;
40+
import org.springframework.grpc.server.ServerServiceDefinitionFilter;
3941
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
4042
import org.springframework.grpc.server.service.GrpcServiceDiscoverer;
4143

@@ -61,7 +63,7 @@ static class ShadedNettyServerFactoryConfiguration {
6163
@Bean
6264
ShadedNettyGrpcServerFactory shadedNettyGrpcServerFactory(GrpcServerProperties properties,
6365
GrpcServiceDiscoverer grpcServicesDiscoverer, ServerBuilderCustomizers serverBuilderCustomizers,
64-
SslBundles bundles) {
66+
SslBundles bundles, Optional<ServerServiceDefinitionFilter> serviceFilter) {
6567
ShadedNettyServerFactoryPropertyMapper mapper = new ShadedNettyServerFactoryPropertyMapper(properties);
6668
List<ServerBuilderCustomizer<io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder>> builderCustomizers = List
6769
.of(mapper::customizeServerBuilder, serverBuilderCustomizers::customize);
@@ -74,7 +76,8 @@ ShadedNettyGrpcServerFactory shadedNettyGrpcServerFactory(GrpcServerProperties p
7476
: io.grpc.netty.shaded.io.netty.handler.ssl.util.InsecureTrustManagerFactory.INSTANCE;
7577
}
7678
ShadedNettyGrpcServerFactory factory = new ShadedNettyGrpcServerFactory(properties.getAddress(),
77-
builderCustomizers, keyManager, trustManager, properties.getSsl().getClientAuth());
79+
builderCustomizers, keyManager, trustManager, properties.getSsl().getClientAuth(),
80+
serviceFilter.orElse(null));
7881
grpcServicesDiscoverer.findServices().forEach(factory::addService);
7982
return factory;
8083
}
@@ -100,7 +103,7 @@ static class NettyServerFactoryConfiguration {
100103
@Bean
101104
NettyGrpcServerFactory nettyGrpcServerFactory(GrpcServerProperties properties,
102105
GrpcServiceDiscoverer grpcServicesDiscoverer, ServerBuilderCustomizers serverBuilderCustomizers,
103-
SslBundles bundles) {
106+
SslBundles bundles, Optional<ServerServiceDefinitionFilter> serviceFilter) {
104107
NettyServerFactoryPropertyMapper mapper = new NettyServerFactoryPropertyMapper(properties);
105108
List<ServerBuilderCustomizer<NettyServerBuilder>> builderCustomizers = List
106109
.of(mapper::customizeServerBuilder, serverBuilderCustomizers::customize);
@@ -113,7 +116,7 @@ NettyGrpcServerFactory nettyGrpcServerFactory(GrpcServerProperties properties,
113116
: InsecureTrustManagerFactory.INSTANCE;
114117
}
115118
NettyGrpcServerFactory factory = new NettyGrpcServerFactory(properties.getAddress(), builderCustomizers,
116-
keyManager, trustManager, properties.getSsl().getClientAuth());
119+
keyManager, trustManager, properties.getSsl().getClientAuth(), serviceFilter.orElse(null));
117120
grpcServicesDiscoverer.findServices().forEach(factory::addService);
118121
return factory;
119122
}

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

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2023-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
2929

3030
import org.assertj.core.api.InstanceOfAssertFactories;
3131
import org.junit.jupiter.api.BeforeEach;
32+
import org.junit.jupiter.api.Nested;
3233
import org.junit.jupiter.api.Test;
3334
import org.mockito.InOrder;
3435
import org.mockito.MockedStatic;
@@ -44,11 +45,13 @@
4445
import org.springframework.context.annotation.Bean;
4546
import org.springframework.context.annotation.Configuration;
4647
import org.springframework.core.annotation.Order;
48+
import org.springframework.grpc.server.DefaultGrpcServerFactory;
4749
import org.springframework.grpc.server.GrpcServerFactory;
4850
import org.springframework.grpc.server.InProcessGrpcServerFactory;
4951
import org.springframework.grpc.server.NettyGrpcServerFactory;
5052
import org.springframework.grpc.server.ServerBuilderCustomizer;
5153
import org.springframework.grpc.server.ShadedNettyGrpcServerFactory;
54+
import org.springframework.grpc.server.ServerServiceDefinitionFilter;
5255
import org.springframework.grpc.server.lifecycle.GrpcServerLifecycle;
5356
import org.springframework.grpc.server.service.DefaultGrpcServiceConfigurer;
5457
import org.springframework.grpc.server.service.GrpcServiceConfigurer;
@@ -65,6 +68,7 @@
6568
* Tests for {@link GrpcServerAutoConfiguration}.
6669
*
6770
* @author Chris Bono
71+
* @author Andrey Litvitski
6872
*/
6973
class GrpcServerAutoConfigurationTests {
7074

@@ -408,6 +412,47 @@ void nettyServerFactoryAutoConfiguredWithSsl() {
408412
NettyGrpcServerFactory.class, "myhost:6160", "nettyGrpcServerLifecycle");
409413
}
410414

415+
@Nested
416+
class WithFilter {
417+
418+
@Test
419+
void whenFilterExcludesOneServiceThenServerListGetAllowedOnes() {
420+
ServerServiceDefinition serviceDefinitionA = mock();
421+
GrpcServerAutoConfigurationTests.this.contextRunner()
422+
.withBean(ServerServiceDefinitionFilter.class,
423+
() -> (serviceDefinition, ___) -> serviceDefinition.equals(serviceDefinitionA))
424+
.run((context) -> {
425+
DefaultGrpcServerFactory<?> defaultGrpcServerFactory = (DefaultGrpcServerFactory<?>) context
426+
.getBean(GrpcServerFactory.class);
427+
ServerServiceDefinition serviceDefinitionB = mock();
428+
defaultGrpcServerFactory.addService(serviceDefinitionA);
429+
defaultGrpcServerFactory.addService(serviceDefinitionB);
430+
assertThat(context).getBean(GrpcServerFactory.class)
431+
.extracting("serviceList", InstanceOfAssertFactories.list(ServerServiceDefinition.class))
432+
.contains(serviceDefinitionA)
433+
.doesNotContain(serviceDefinitionB);
434+
});
435+
}
436+
437+
@Test
438+
void whenFilterIncludesAllServicesThenServerListGetAllowedOnes() {
439+
GrpcServerAutoConfigurationTests.this.contextRunner()
440+
.withBean(ServerServiceDefinitionFilter.class, () -> (__, ___) -> true)
441+
.run((context) -> {
442+
DefaultGrpcServerFactory<?> defaultGrpcServerFactory = (DefaultGrpcServerFactory<?>) context
443+
.getBean(GrpcServerFactory.class);
444+
ServerServiceDefinition serviceDefinitionA = mock();
445+
ServerServiceDefinition serviceDefinitionB = mock();
446+
defaultGrpcServerFactory.addService(serviceDefinitionA);
447+
defaultGrpcServerFactory.addService(serviceDefinitionB);
448+
assertThat(context).getBean(GrpcServerFactory.class)
449+
.extracting("serviceList", InstanceOfAssertFactories.list(ServerServiceDefinition.class))
450+
.contains(serviceDefinitionA, serviceDefinitionB);
451+
});
452+
}
453+
454+
}
455+
411456
@Configuration(proxyBeanMethods = false)
412457
static class ServerBuilderCustomizersConfig {
413458

0 commit comments

Comments
 (0)