Skip to content

Commit 8d064e9

Browse files
Fix ManagedChannelsImpl channel retrieval issue (#115)
* fix: resolve ManagedChannelsImpl channel retrieval issue - Fix ManagedChannelsImpl to proactively create channels when not found in cache - Ensure channels are properly initialized and cached on demand - Resolves issue where getChannel() throws exception for configured channels Fixes #114 * fix: update ManagedChannels retrieval for User and Order services
1 parent 897bec0 commit 8d064e9

File tree

7 files changed

+66
-74
lines changed

7 files changed

+66
-74
lines changed

examples/quick-start/src/main/java/grpcstarter/example/QuickStartApp.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package grpcstarter.example;
22

3+
import grpcstarter.client.ManagedChannels;
34
import io.grpc.testing.protobuf.SimpleRequest;
45
import io.grpc.testing.protobuf.SimpleServiceGrpc;
56
import order.v1.GetOrdersByUserIdRequest;
@@ -42,4 +43,14 @@ ApplicationRunner runner(
4243
System.out.println("Orders: " + orders);
4344
};
4445
}
46+
47+
@Bean
48+
UserServiceGrpc.UserServiceBlockingStub userStub(ManagedChannels channels) {
49+
return UserServiceGrpc.newBlockingStub(channels.getChannel("channel-1"));
50+
}
51+
52+
@Bean
53+
OrderServiceGrpc.OrderServiceBlockingStub orderStub(ManagedChannels channels) {
54+
return OrderServiceGrpc.newBlockingStub(channels.getChannel("channel-1"));
55+
}
4556
}

examples/quick-start/src/main/resources/application.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ grpc:
88
channels:
99
- authority: localhost:${grpc.server.port}
1010
stubs: [ io.grpc.testing.** ]
11-
- authority: 127.0.0.1:${grpc.server.port}
12-
stubs: [ user.v1.**, order.v1.** ]
11+
- name: channel-1
12+
authority: 127.0.0.1:${grpc.server.port}

grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/Cache.java

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import static grpcstarter.client.Util.shutdownChannel;
55

66
import io.grpc.ManagedChannel;
7-
import jakarta.annotation.Nullable;
87
import java.time.Duration;
98
import java.util.ArrayList;
109
import java.util.Collections;
@@ -18,7 +17,6 @@
1817
import java.util.stream.Collectors;
1918
import org.slf4j.Logger;
2019
import org.slf4j.LoggerFactory;
21-
import org.springframework.util.StringUtils;
2220

2321
/**
2422
* @author Freeman
@@ -39,11 +37,6 @@ private Cache() {
3937
private static final Map<GrpcClientProperties.Channel, ManagedChannel> cfgToChannel =
4038
Collections.synchronizedMap(new LinkedHashMap<>());
4139

42-
/**
43-
* Cache channel name to ManagedChannel mapping.
44-
*/
45-
private static final ConcurrentMap<String, ManagedChannel> nameToChannel = new ConcurrentHashMap<>();
46-
4740
public static Set<Class<?>> getStubClasses() {
4841
return serviceToStubClasses.values().stream().flatMap(List::stream).collect(Collectors.toSet());
4942
}
@@ -63,18 +56,7 @@ public static void addStubClass(Class<?> stubClass) {
6356
public static ManagedChannel getOrSupplyChannel(
6457
GrpcClientProperties.Channel channelConfig, Supplier<ManagedChannel> channelSupplier) {
6558
// Do not close the channel if it already exists, it may be still in use
66-
ManagedChannel channel = cfgToChannel.computeIfAbsent(channelConfig, k -> channelSupplier.get());
67-
68-
// Also cache by name
69-
String channelName = channelConfig.getName();
70-
if (!StringUtils.hasText(channelName)) {
71-
throw new IllegalArgumentException(
72-
"Channel name must not be null or empty, authority: " + channelConfig.getAuthority());
73-
}
74-
75-
nameToChannel.put(channelName, channel);
76-
77-
return channel;
59+
return cfgToChannel.computeIfAbsent(channelConfig, k -> channelSupplier.get());
7860
}
7961

8062
/**
@@ -97,18 +79,6 @@ public static void shutdownChannels() {
9779
System.currentTimeMillis() - start);
9880
}
9981
cfgToChannel.clear();
100-
nameToChannel.clear();
101-
}
102-
103-
/**
104-
* Get a ManagedChannel by name.
105-
*
106-
* @param name the channel name
107-
* @return the managed channel, or null if not found
108-
*/
109-
@Nullable
110-
public static ManagedChannel getChannelByName(String name) {
111-
return nameToChannel.get(name);
11282
}
11383

11484
public static void clear() {

grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientAutoConfiguration.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static grpcstarter.client.Checker.checkUnusedConfig;
44

55
import grpcstarter.server.GrpcServerShutdownEvent;
6+
import org.springframework.beans.factory.BeanFactory;
67
import org.springframework.beans.factory.DisposableBean;
78
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
89
import org.springframework.boot.CommandLineRunner;
@@ -48,8 +49,9 @@ public GrpcClientOptionsClientInterceptor grpcClientOptionsClientInterceptor() {
4849

4950
@Bean
5051
@ConditionalOnMissingBean
51-
public ManagedChannels grpcClientManagedChannels() {
52-
return new ManagedChannelsImpl();
52+
public ManagedChannels grpcClientManagedChannels(
53+
BeanFactory beanFactory, GrpcClientProperties grpcClientProperties) {
54+
return new ManagedChannelsImpl(beanFactory, grpcClientProperties);
5355
}
5456

5557
@Bean

grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ static GrpcClientProperties.Refresh getRefresh(Environment environment) {
166166
.orElseGet(GrpcClientProperties.Refresh::new);
167167
}
168168

169-
private static ManagedChannel createChannel(BeanFactory beanFactory, GrpcClientProperties.Channel channelConfig) {
169+
static ManagedChannel createChannel(BeanFactory beanFactory, GrpcClientProperties.Channel channelConfig) {
170170
checkValid(channelConfig);
171171
return new GrpcChannelCreator(beanFactory, channelConfig).create();
172172
}
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package grpcstarter.client;
22

33
import io.grpc.ManagedChannel;
4+
import org.springframework.beans.factory.BeanFactory;
45

56
/**
67
* Default implementation of {@link ManagedChannels}.
@@ -10,12 +11,20 @@
1011
*/
1112
class ManagedChannelsImpl implements ManagedChannels {
1213

14+
private final BeanFactory beanFactory;
15+
private final GrpcClientProperties properties;
16+
17+
ManagedChannelsImpl(BeanFactory beanFactory, GrpcClientProperties properties) {
18+
this.beanFactory = beanFactory;
19+
this.properties = properties;
20+
}
21+
1322
@Override
1423
public ManagedChannel getChannel(String name) {
15-
ManagedChannel channel = Cache.getChannelByName(name);
16-
if (channel == null) {
24+
var channelConfig = Util.findChannelByName(name, properties);
25+
if (channelConfig == null) {
1726
throw new IllegalArgumentException("No channel found with name: " + name);
1827
}
19-
return channel;
28+
return GrpcClientUtil.createChannel(beanFactory, channelConfig);
2029
}
2130
}

website/docs/40-configuration-properties.md

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -80,56 +80,56 @@ This page was generated by [spring-configuration-property-documenter](https://gi
8080

8181
|Key|Type|Description|Default value|Deprecation|
8282
|---|----|-----------|-------------|-----------|
83-
| cert-chain| org.springframework.core.io.Resource| @see TlsChannelCredentials.Builder#getCertificateChain()| | |
84-
| private-key| org.springframework.core.io.Resource| @see TlsChannelCredentials.Builder#getPrivateKey()| | |
85-
| private-key-password| java.lang.String| @see TlsChannelCredentials.Builder#getPrivateKeyPassword()| | |
83+
| cert-chain| org.springframework.core.io.Resource| | | |
84+
| private-key| org.springframework.core.io.Resource| | | |
85+
| private-key-password| java.lang.String| | | |
8686
### grpc.client.tls.trust-manager
8787
**Class:** `grpcstarter.client.GrpcClientProperties$Tls$TrustManager`
8888

8989
|Key|Type|Description|Default value|Deprecation|
9090
|---|----|-----------|-------------|-----------|
91-
| root-certs| org.springframework.core.io.Resource| @see TlsChannelCredentials.Builder#getRootCertificates()| | |
91+
| root-certs| org.springframework.core.io.Resource| | | |
9292
### grpc.client
9393
**Class:** `grpcstarter.client.GrpcClientProperties`
9494

9595
|Key|Type|Description|Default value|Deprecation|
9696
|---|----|-----------|-------------|-----------|
97-
| authority| java.lang.String| Default authority. &lt;p&gt; e.g. localhost:8080 &lt;/p&gt;| | |
98-
| base-packages| java.util.List&lt;java.lang.String&gt;| Base packages to scan for gRPC stubs. &lt;p&gt; This value will merge with \{@link EnableGrpcClients#basePackages}. &lt;p&gt; The advantage of using configuration is no need to introduce external annotations. &lt;/p&gt;| | |
99-
| bean-definition-handler| java.lang.Class&lt;? extends grpcstarter.client.GrpcClientBeanDefinitionHandler&gt;| gRPC client bean definition handler, used to customize the bean definition before registering. &lt;p&gt; Use \{@link GrpcClientBeanDefinitionHandler} if not set. &lt;p&gt; Implementation must have a public no-args constructor. @since 3.4.3.1| | |
100-
| channels| java.util.List&lt;grpcstarter.client.GrpcClientProperties$Channel&gt;| Channels configuration.| | |
101-
| clients| java.util.List&lt;java.lang.Class&lt;? extends io.grpc.stub.AbstractStub&gt;&gt;| The clients used to register as Spring beans. &lt;p&gt; This value will merge with \{@link EnableGrpcClients#clients}. &lt;p&gt; &#x60;clients&#x60; and \{@link #basePackages} represent two different configuration methods. \{@link #basePackages} is through package scanning, and &#x60;clients&#x60; is through class name. &lt;p&gt; The &#x60;clients&#x60; configuration can avoid classpath scanning, resulting in faster startup, and it has better IDE support.| | |
102-
| compression| java.lang.String| Compression configuration. @see AbstractStub#withCompression(String)| | |
103-
| deadline| java.lang.Long| Deadline after in milliseconds, default value is 5000. @see AbstractStub#withDeadline(Deadline) @since 3.2.0| | |
104-
| enabled| java.lang.Boolean| Whether to enable gRPC client autoconfiguration, default true.| true| |
105-
| max-inbound-message-size| org.springframework.util.unit.DataSize| Default max inbound message size, default value is 4MB. @see DataSize @see GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE| | |
106-
| max-inbound-metadata-size| org.springframework.util.unit.DataSize| Default max metadata size, default value is 8KB. @see DataSize @see GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE| | |
107-
| max-outbound-message-size| org.springframework.util.unit.DataSize| Default max outbound message size. @see DataSize @see AbstractStub#withMaxOutboundMessageSize(int)| | |
108-
| metadata| java.util.List&lt;grpcstarter.client.GrpcClientProperties$Metadata&gt;| Default metadata will be added to all the gRPC requests.| | |
109-
| shutdown-timeout| java.lang.Long| Channel shutdown timeout in milliseconds, default value is 5000.| 5000| |
110-
| ssl-bundle| java.lang.String| SSL bundle name to use for secure connections. &lt;p&gt;References an SSL bundle configured under \{@code spring.ssl.bundle.*}. This is the preferred way to configure SSL/TLS for gRPC clients. @since 3.5.3| | |
111-
| warn-unused-config-enabled| java.lang.Boolean| Whether to enable warn unused config, default true.| true| |
97+
| authority| java.lang.String| | | |
98+
| base-packages| java.util.List&lt;java.lang.String&gt;| | | |
99+
| bean-definition-handler| java.lang.Class&lt;? extends grpcstarter.client.GrpcClientBeanDefinitionHandler&gt;| | | |
100+
| channels| java.util.List&lt;grpcstarter.client.GrpcClientProperties$Channel&gt;| | | |
101+
| clients| java.util.List&lt;java.lang.Class&lt;? extends io.grpc.stub.AbstractStub&gt;&gt;| | | |
102+
| compression| java.lang.String| | | |
103+
| deadline| java.lang.Long| | | |
104+
| enabled| java.lang.Boolean| | | |
105+
| max-inbound-message-size| org.springframework.util.unit.DataSize| | | |
106+
| max-inbound-metadata-size| org.springframework.util.unit.DataSize| | | |
107+
| max-outbound-message-size| org.springframework.util.unit.DataSize| | | |
108+
| metadata| java.util.List&lt;grpcstarter.client.GrpcClientProperties$Metadata&gt;| | | |
109+
| shutdown-timeout| java.lang.Long| | | |
110+
| ssl-bundle| java.lang.String| | | |
111+
| warn-unused-config-enabled| java.lang.Boolean| | | |
112112
### grpc.client.in-process
113113
**Class:** `grpcstarter.client.GrpcClientProperties$InProcess`
114114

115115
|Key|Type|Description|Default value|Deprecation|
116116
|---|----|-----------|-------------|-----------|
117-
| name| java.lang.String| In-process client name. &lt;p&gt; If set, will create an in-process channel by default, usually for testing. &lt;/p&gt;| | |
117+
| name| java.lang.String| | | |
118118
### grpc.client.refresh
119119
**Class:** `grpcstarter.client.GrpcClientProperties$Refresh`
120120

121121
|Key|Type|Description|Default value|Deprecation|
122122
|---|----|-----------|-------------|-----------|
123-
| enabled| java.lang.Boolean| Whether to enable refresh grpc clients, default false. &lt;p&gt; NOTE: this feature needs &#x27;spring-cloud-context&#x27; dependency in the classpath. &lt;/p&gt;| false| |
123+
| enabled| java.lang.Boolean| | | |
124124
### grpc.client.retry
125125
**Class:** `grpcstarter.client.GrpcClientProperties$Retry`
126126

127127
|Key|Type|Description|Default value|Deprecation|
128128
|---|----|-----------|-------------|-----------|
129-
| enabled| java.lang.Boolean| Whether to enable retry. @see io.grpc.ManagedChannelBuilder#enableRetry() @see io.grpc.ManagedChannelBuilder#disableRetry()| | |
130-
| max-retry-attempts| java.lang.Integer| Maximum number of attempts to retry. @see io.grpc.ManagedChannelBuilder#maxRetryAttempts(int)| | |
131-
| per-rpc-buffer-limit| org.springframework.util.unit.DataSize| The maximum number of retry buffer entries per RPC. @see io.grpc.ManagedChannelBuilder#perRpcBufferLimit(long)| | |
132-
| retry-buffer-size| org.springframework.util.unit.DataSize| The maximum number of retry buffer entries. @see io.grpc.ManagedChannelBuilder#retryBufferSize(long)| | |
129+
| enabled| java.lang.Boolean| | | |
130+
| max-retry-attempts| java.lang.Integer| | | |
131+
| per-rpc-buffer-limit| org.springframework.util.unit.DataSize| | | |
132+
| retry-buffer-size| org.springframework.util.unit.DataSize| | | |
133133
### grpc.client.tls
134134
**Class:** `grpcstarter.client.GrpcClientProperties$Tls`
135135

@@ -228,21 +228,21 @@ This page was generated by [spring-configuration-property-documenter](https://gi
228228

229229
|Key|Type|Description|Default value|Deprecation|
230230
|---|----|-----------|-------------|-----------|
231-
| enabled| java.lang.Boolean| whether to enable metrics, default is \{@code true}| true| |
231+
| enabled| java.lang.Boolean| | | |
232232
### grpc.metrics.client
233233
**Class:** `grpcstarter.extensions.metrics.GrpcMetricsProperties$Client`
234234

235235
|Key|Type|Description|Default value|Deprecation|
236236
|---|----|-----------|-------------|-----------|
237-
| enabled| java.lang.Boolean| whether to enable client metrics, default is \{@code true}| true| |
238-
| order| java.lang.Integer| The order of the client metrics interceptor. Default is \{@code 0}.| 0| |
237+
| enabled| java.lang.Boolean| | | |
238+
| order| java.lang.Integer| | | |
239239
### grpc.metrics.server
240240
**Class:** `grpcstarter.extensions.metrics.GrpcMetricsProperties$Server`
241241

242242
|Key|Type|Description|Default value|Deprecation|
243243
|---|----|-----------|-------------|-----------|
244-
| enabled| java.lang.Boolean| whether to enable server metrics, default is \{@code true}| true| |
245-
| order| java.lang.Integer| The order of the server metrics interceptor. Default is \{@code 0}.| 0| |
244+
| enabled| java.lang.Boolean| | | |
245+
| order| java.lang.Integer| | | |
246246

247247
## grpc-test
248248
### grpc.test
@@ -265,21 +265,21 @@ This page was generated by [spring-configuration-property-documenter](https://gi
265265

266266
|Key|Type|Description|Default value|Deprecation|
267267
|---|----|-----------|-------------|-----------|
268-
| enabled| java.lang.Boolean| whether to enable tracing, default is \{@code true}| true| |
268+
| enabled| java.lang.Boolean| | | |
269269
### grpc.tracing.client
270270
**Class:** `grpcstarter.extensions.tracing.GrpcTracingProperties$Client`
271271

272272
|Key|Type|Description|Default value|Deprecation|
273273
|---|----|-----------|-------------|-----------|
274-
| enabled| java.lang.Boolean| whether to enable client tracing, default is \{@code true}| true| |
275-
| order| java.lang.Integer| The order of the client tracing interceptor. Default is \{@code 0}.| 0| |
274+
| enabled| java.lang.Boolean| | | |
275+
| order| java.lang.Integer| | | |
276276
### grpc.tracing.server
277277
**Class:** `grpcstarter.extensions.tracing.GrpcTracingProperties$Server`
278278

279279
|Key|Type|Description|Default value|Deprecation|
280280
|---|----|-----------|-------------|-----------|
281-
| enabled| java.lang.Boolean| whether to enable server tracing, default is \{@code true}| true| |
282-
| order| java.lang.Integer| The order of the server tracing interceptor. Default is \{@code 0}.| 0| |
281+
| enabled| java.lang.Boolean| | | |
282+
| order| java.lang.Integer| | | |
283283

284284
## grpc-transcoding
285285
### grpc.transcoding

0 commit comments

Comments
 (0)