Skip to content

Commit e334c1b

Browse files
authored
Add support for @GrpcClientBean (#580)
2 parents 3236156 + 18ea434 commit e334c1b

File tree

8 files changed

+628
-27
lines changed

8 files changed

+628
-27
lines changed

docs/en/client/configuration.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This section describes how you can configure your grpc-spring-boot-starter clien
99
- [Configuration via Properties](#configuration-via-properties)
1010
- [Choosing the Target](#choosing-the-target)
1111
- [Configuration via Beans](#configuration-via-beans)
12+
- [GrpcClientBean](#grpcclientbean)
1213
- [GrpcChannelConfigurer](#grpcchannelconfigurer)
1314
- [ClientInterceptor](#clientinterceptor)
1415
- [StubFactory](#stubfactory)
@@ -115,6 +116,50 @@ First of all most of the beans can be replaced by custom ones, that you can conf
115116
If you don't wish to go that far, you can use classes such as `GrpcChannelConfigurer` and `StubTransformer` to configure
116117
the channels, stubs and other components without losing the features provided by this library.
117118

119+
### GrpcClientBean
120+
121+
This annotation is used to create injectable beans from your otherwise non-injectable `@GrpcClient` instances.
122+
The annotation can be repeatedly added to any of your `@Configuration` classes.
123+
124+
> **Note:** We recommend using either `@GrpcClientBean`s or fields annotated with `@GrpcClient` throughout your
125+
> application, as mixing the two might cause confusion for future developers.
126+
127+
````java
128+
@Configuration
129+
@GrpcClientBean(
130+
clazz = TestServiceBlockingStub.class,
131+
beanName = "blockingStub",
132+
client = @GrpcClient("test")
133+
)
134+
@GrpcClientBean(
135+
clazz = FactoryMethodAccessibleStub.class,
136+
beanName = "accessibleStub",
137+
client = @GrpcClient("test"))
138+
public class YourCustomConfiguration {
139+
140+
@Bean
141+
FooService fooServiceBean(@Autowired TestServiceGrpc.TestServiceBlockingStub blockingStub) {
142+
return new FooService(blockingStub);
143+
}
144+
145+
}
146+
147+
@Service
148+
@AllArgsConsturtor
149+
public class BarService {
150+
151+
private FactoryMethodAccessibleStub accessibleStub;
152+
153+
public String receiveGreeting(String name) {
154+
HelloRequest request = HelloRequest.newBuilder()
155+
.setName(name)
156+
.build();
157+
return accessibleStub.sayHello(request).getMessage();
158+
}
159+
160+
}
161+
````
162+
118163
### GrpcChannelConfigurer
119164

120165
The grpc client configurer allows you to add your custom configuration to grpc's `ManagedChannelBuilder`s.

docs/en/client/getting-started.md

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,14 @@ If you don't wish to use any advanced features, then the first element is probab
106106
The annotation that marks fields and setters for auto injection of clients.
107107
Supports `Channel`s, and all kinds of `Stub`s.
108108
Do not use `@GrpcClient` in conjunction with `@Autowired` or `@Inject`.
109-
Currently it isn't supported for constructor and `@Bean` method parameters. \
109+
Currently, it isn't supported for constructor and `@Bean` method parameters. For this case look below
110+
to the `@GrpcClientBean`. \
110111
**Note:** Services provided by the same application can only be accessed/called in/after the
111112
`ApplicationStartedEvent`. Stubs connecting to services outside of the application can be used earlier; starting with
112113
`@PostConstruct` / `InitializingBean#afterPropertiesSet()`.
114+
- [`@GrpcClientBean`](https://javadoc.io/page/net.devh/grpc-client-spring-boot-autoconfigure/latest/net/devh/boot/grpc/client/inject/GrpcClientBean.html):
115+
The annotation helps to register `@GrpcClient` beans in the Spring context to be used with `@Autowired` and
116+
`@Qualifier`. The annotation can be repeatedly added to any of your `@Configuration` classes.
113117
- [`Channel`](https://javadoc.io/page/io.grpc/grpc-all/latest/io/grpc/Channel.html):
114118
The Channel is a connection pool for a single address. The target servers might serve multiple grpc-services though.
115119
The address will be resolved using a `NameResolver` and might point to a fixed or dynamic number of servers.
@@ -167,13 +171,51 @@ public class FoobarService {
167171
public String receiveGreeting(String name) {
168172
HelloRequest request = HelloRequest.newBuilder()
169173
.setName(name)
170-
.build()
174+
.build();
171175
return myServiceStub.sayHello(request).getMessage();
172176
}
173177

174178
}
175179
````
176180

181+
Also you can feel free to inject stub with `@GrpcClientBean` with `@Configuration` for more wide usage in
182+
another services.
183+
184+
> **Note:** We recommend using either `@GrpcClientBean`s or fields annotated with `@GrpcClient` throughout your
185+
> application, as mixing the two can cause confusion for future developers.
186+
187+
````java
188+
@Configuration
189+
@GrpcClientBean(
190+
clazz = TestServiceGrpc.TestServiceBlockingStub.class,
191+
beanName = "blockingStub",
192+
client = @GrpcClient("test")
193+
)
194+
public class YourCustomConfiguration {
195+
196+
@Bean
197+
FoobarService foobarService(@Autowired TestServiceGrpc.TestServiceBlockingStub blockingStub) {
198+
return new FoobarService(blockingStub);
199+
}
200+
201+
}
202+
203+
@Service
204+
@AllArgsConsturtor
205+
public class FoobarService {
206+
207+
private TestServiceBlockingStub blockingStub;
208+
209+
public String receiveGreeting(String name) {
210+
HelloRequest request = HelloRequest.newBuilder()
211+
.setName(name)
212+
.build();
213+
return blockingStub.sayHello(request).getMessage();
214+
}
215+
216+
}
217+
````
218+
177219
## Additional Topics <!-- omit in toc -->
178220

179221
- *Getting Started*

grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClient.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import javax.inject.Inject;
2828

2929
import org.springframework.beans.factory.annotation.Autowired;
30+
import org.springframework.context.ApplicationContext;
3031

3132
import io.grpc.CallCredentials;
3233
import io.grpc.CallOptions;
@@ -39,7 +40,7 @@
3940

4041
/**
4142
* An annotation for fields of type {@link Channel} or subclasses of {@link AbstractStub}/gRPC client services. Also
42-
* works for annotated methods that only take a single parameter of the same types. Annotated fields/methods will be
43+
* works for annotated methods that only take a single parameter of these types. Annotated fields/methods will be
4344
* automatically populated/invoked by Spring.
4445
*
4546
* <p>
@@ -59,8 +60,7 @@
5960
* interceptors and applied using {@link ClientInterceptors#interceptForward(Channel, ClientInterceptor...)}.
6061
* </p>
6162
*
62-
* @author Michael ([email protected])
63-
* @since 2016/12/7
63+
* @see GrpcClientBean Add as bean to the {@link ApplicationContext}.
6464
*/
6565
@Target({ElementType.FIELD, ElementType.METHOD})
6666
@Retention(RetentionPolicy.RUNTIME)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2016-2021 Michael Zhang <[email protected]>
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
7+
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package net.devh.boot.grpc.client.inject;
19+
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Repeatable;
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
24+
import java.lang.annotation.Target;
25+
26+
import org.springframework.context.ApplicationContext;
27+
import org.springframework.context.annotation.Configuration;
28+
29+
/**
30+
* Annotation that can be added to {@link Configuration} classes to add a {@link GrpcClient} bean to the
31+
* {@link ApplicationContext}.
32+
*/
33+
@Target(ElementType.TYPE)
34+
@Repeatable(GrpcClientBeans.class)
35+
@Retention(RetentionPolicy.RUNTIME)
36+
public @interface GrpcClientBean {
37+
38+
/**
39+
* The type of the bean to create.
40+
*
41+
* @return The type of the bean.
42+
*/
43+
Class<?> clazz();
44+
45+
/**
46+
* The name of the bean to create. If empty, a name will be generated automatically based on the bean class and the
47+
* client name.
48+
*
49+
* @return The optional name of the bean.
50+
*/
51+
String beanName() default "";
52+
53+
/**
54+
* The client definition used to create the channel and grab all properties.
55+
*
56+
* @return The client definition to use.
57+
*/
58+
GrpcClient client();
59+
60+
}

0 commit comments

Comments
 (0)