Skip to content

Commit f0ec4b1

Browse files
author
Dave Syer
committed
Add support for registering service definition bean
1 parent 7fed50a commit f0ec4b1

File tree

4 files changed

+31
-7
lines changed

4 files changed

+31
-7
lines changed

spring-grpc-docs/src/main/antora/modules/ROOT/pages/server.adoc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ This section describes core concepts that Spring gRPC uses on the server side. W
55
You only need to provide one or more beans of type `BindableService` to create a gRPC server, provided the classpath contains an implementation of a `Server`. The `BindableService` is a gRPC service that can be bound to a server.
66
The `Server` is the gRPC server that listens for incoming requests and routes them to the appropriate service implementation.
77

8-
== Create a `BindableService`
8+
== Create a gRPC Service
99

10-
To create a gRPC server, you need to provide one or more beans of type `BindableService`.
10+
To create a gRPC server, you need to provide one or more beans of type `BindableService` or `ServerServiceDefinition`.
1111
There are some `BindableServices` available off the shelf that you could include in your application (an example is the reflection service from the `grpc-services` artifact which allows clients to browse the metadata of your services and download the Portobuf files).
1212
Very commonly, you will create your own `BindableService` by extending the generated service implementation from your Protobuf file.
13-
The easiest way to do it is to simply add a Spring `@Service` annotation to the implementation class and have it picked up by the `@ComponentScan` in your Spring Boot application.
13+
The easiest way to activate it is to simply add a Spring `@Service` annotation to the implementation class and have it picked up by the `@ComponentScan` in your Spring Boot application.
14+
Alternatively, you could create an instance of it in a `@Configuration` class and return it as a bean, or return it's `ServerServiceDefinition`.
15+
The last option is useful if you need to add specific behaviour, like an interceptor, to the service.
16+
It is an error to have more than one instance of the same service name, so don't create both a `BindableService` and a `ServerServiceDefinition` bean for the same service.
1417

1518
== Netty Server
1619

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.grpc.autoconfigure.server;
1818

19+
import java.util.ArrayList;
1920
import java.util.List;
2021

2122
import io.grpc.BindableService;
@@ -35,13 +36,20 @@ class DefaultGrpcServiceDiscoverer implements GrpcServiceDiscoverer {
3536

3637
private final ObjectProvider<BindableService> grpcServicesProvider;
3738

38-
DefaultGrpcServiceDiscoverer(ObjectProvider<BindableService> grpcServicesProvider) {
39+
private ObjectProvider<ServerServiceDefinition> grpcServiceDefinitionsProvider;
40+
41+
DefaultGrpcServiceDiscoverer(ObjectProvider<BindableService> grpcServicesProvider,
42+
ObjectProvider<ServerServiceDefinition> grpcServiceDefinitionsProvider) {
3943
this.grpcServicesProvider = grpcServicesProvider;
44+
this.grpcServiceDefinitionsProvider = grpcServiceDefinitionsProvider;
4045
}
4146

4247
@Override
4348
public List<ServerServiceDefinition> findServices() {
44-
return grpcServicesProvider.orderedStream().map(BindableService::bindService).toList();
49+
List<ServerServiceDefinition> list = new ArrayList<>(
50+
grpcServicesProvider.orderedStream().map(BindableService::bindService).toList());
51+
list.addAll(grpcServiceDefinitionsProvider.orderedStream().toList());
52+
return list;
4553
}
4654

4755
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import io.grpc.CompressorRegistry;
3737
import io.grpc.DecompressorRegistry;
3838
import io.grpc.ServerBuilder;
39+
import io.grpc.ServerServiceDefinition;
3940

4041
/**
4142
* {@link EnableAutoConfiguration Auto-configuration} for gRPC server-side components.
@@ -75,8 +76,9 @@ ServerBuilderCustomizers serverBuilderCustomizers(ObjectProvider<ServerBuilderCu
7576

7677
@ConditionalOnMissingBean
7778
@Bean
78-
GrpcServiceDiscoverer grpcServiceDiscoverer(ObjectProvider<BindableService> bindableServicesProvider) {
79-
return new DefaultGrpcServiceDiscoverer(bindableServicesProvider);
79+
GrpcServiceDiscoverer grpcServiceDiscoverer(ObjectProvider<BindableService> bindableServicesProvider,
80+
ObjectProvider<ServerServiceDefinition> serviceDefinitionsProvider) {
81+
return new DefaultGrpcServiceDiscoverer(bindableServicesProvider, serviceDefinitionsProvider);
8082
}
8183

8284
@ConditionalOnBean(CompressorRegistry.class)

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@ void grpcServiceDiscovererAutoConfiguredAsExpected() {
134134
.containsExactly(this.serviceDefinition));
135135
}
136136

137+
@Test
138+
void grpcServiceDiscovererWithServiceDefinitionAsExpected() {
139+
ServerServiceDefinition serviceDefinition = ServerServiceDefinition.builder("my-other-service").build();
140+
this.contextRunnerWithLifecyle()
141+
.withBean(ServerServiceDefinition.class, () -> serviceDefinition)
142+
.run((context) -> assertThat(context).getBean(GrpcServiceDiscoverer.class)
143+
.extracting(GrpcServiceDiscoverer::findServices,
144+
InstanceOfAssertFactories.list(ServerServiceDefinition.class))
145+
.containsExactly(this.serviceDefinition, serviceDefinition));
146+
}
147+
137148
@Test
138149
void whenHasUserDefinedServerBuilderCustomizersDoesNotAutoConfigureBean() {
139150
ServerBuilderCustomizers customCustomizers = mock(ServerBuilderCustomizers.class);

0 commit comments

Comments
 (0)