diff --git a/spring-grpc-core/src/main/java/org/springframework/grpc/client/DefaultGrpcChannelFactory.java b/spring-grpc-core/src/main/java/org/springframework/grpc/client/DefaultGrpcChannelFactory.java index 7bbf373..93563ec 100644 --- a/spring-grpc-core/src/main/java/org/springframework/grpc/client/DefaultGrpcChannelFactory.java +++ b/spring-grpc-core/src/main/java/org/springframework/grpc/client/DefaultGrpcChannelFactory.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.factory.DisposableBean; +import org.springframework.util.Assert; import io.grpc.ChannelCredentials; import io.grpc.ForwardingChannelBuilder2; @@ -44,7 +45,7 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable private final Map channels = new ConcurrentHashMap<>(); - private final List configurers = new ArrayList<>(); + private final List customizers = new ArrayList<>(); private ChannelCredentialsProvider credentials = ChannelCredentialsProvider.INSECURE; @@ -54,8 +55,9 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable this(List.of()); } - public DefaultGrpcChannelFactory(List configurers) { - this.configurers.addAll(configurers); + public DefaultGrpcChannelFactory(List customizers) { + Assert.notNull(customizers, () -> "customizers must not be null"); + this.customizers.addAll(customizers); } public void setVirtualTargets(VirtualTargets targets) { @@ -71,13 +73,10 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable ManagedChannelBuilder target = this.builders.computeIfAbsent(authority, path -> { ManagedChannelBuilder builder = newChannel(this.targets.getTarget(path), this.credentials.getChannelCredentials(path)); - for (GrpcChannelConfigurer configurer : this.configurers) { - configurer.configure(path, builder); - } + this.customizers.forEach((c) -> c.customize(path, builder)); return builder; }); return new DisposableChannelBuilder(authority, target); - } /** @@ -120,9 +119,7 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable @Override public ManagedChannel build() { - ManagedChannel channel = DefaultGrpcChannelFactory.this.channels.computeIfAbsent(this.authority, - name -> super.build()); - return channel; + return DefaultGrpcChannelFactory.this.channels.computeIfAbsent(this.authority, name -> super.build()); } } diff --git a/spring-grpc-core/src/main/java/org/springframework/grpc/client/GrpcChannelConfigurer.java b/spring-grpc-core/src/main/java/org/springframework/grpc/client/GrpcChannelBuilderCustomizer.java similarity index 70% rename from spring-grpc-core/src/main/java/org/springframework/grpc/client/GrpcChannelConfigurer.java rename to spring-grpc-core/src/main/java/org/springframework/grpc/client/GrpcChannelBuilderCustomizer.java index 86a8cfd..3ac7c50 100644 --- a/spring-grpc-core/src/main/java/org/springframework/grpc/client/GrpcChannelConfigurer.java +++ b/spring-grpc-core/src/main/java/org/springframework/grpc/client/GrpcChannelBuilderCustomizer.java @@ -19,21 +19,21 @@ package org.springframework.grpc.client; import io.grpc.ManagedChannelBuilder; /** - * A functional interface for configuring a {@link ManagedChannelBuilder} for a specific - * authority. + * Callback interface that can be used to customize a {@link ManagedChannelBuilder} for a + * specific authority. * * @author Dave Syer * @author Chris Bono - * @see ManagedChannelBuilder */ @FunctionalInterface -public interface GrpcChannelConfigurer { +public interface GrpcChannelBuilderCustomizer { /** - * Configures the given {@link ManagedChannelBuilder} for the specified authority. + * Callback to customize a {@link ManagedChannelBuilder} instance for a specified + * authority. * @param authority the target authority for the channel - * @param builder the builder to configure + * @param builder the builder to customize */ - void configure(String authority, ManagedChannelBuilder builder); + void customize(String authority, ManagedChannelBuilder builder); } diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/nav.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/nav.adoc index d35dc9a..d99339e 100644 --- a/spring-grpc-docs/src/main/antora/modules/ROOT/nav.adoc +++ b/spring-grpc-docs/src/main/antora/modules/ROOT/nav.adoc @@ -1,4 +1,5 @@ * xref:index.adoc[Overview] +* xref:whats-new.adoc[What's new?] * xref:getting-started.adoc[Getting Started] * xref:server.adoc[GRPC Server] * xref:client.adoc[GRPC Clients] diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc index 320f729..811e77a 100644 --- a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc +++ b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc @@ -82,7 +82,7 @@ spring.grpc.client.channels.local.address=0.0.0.0:9090 There is a default named channel (named "default") that you can configure in the same way, and then it will be used by default if there is no channel with the name specified in the channel creation. -Beans of type `GrpcChannelConfigurer` can be used to customize the `ChannelBuilder` before the channel is built. +Beans of type `GrpcChannelBuilderCustomizer` can be used to customize the `ChannelBuilder` before the channel is built. This can be useful for setting up security, for example. == The Local Server Port @@ -99,4 +99,4 @@ The `@Bean` has to be marked as `@Lazy` to ensure that the port is available whe SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels, @LocalGrpcPort int port) { return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:" + port).build()); } ----- \ No newline at end of file +---- diff --git a/spring-grpc-docs/src/main/antora/modules/ROOT/pages/whats-new.adoc b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/whats-new.adoc new file mode 100644 index 0000000..da26d5c --- /dev/null +++ b/spring-grpc-docs/src/main/antora/modules/ROOT/pages/whats-new.adoc @@ -0,0 +1,13 @@ += What's new? + +[[what-s-new-in-0-3-0-since-0-2-0]] +== What's New in 0.3.0 Since 0.2.0 +:page-section-summary-toc: 1 + +This section covers the changes made from version 0.2.0 to version 0.3.0. + + +=== Breaking Changes + +==== GrpcChannelConfigurer renamed +The `GrpcChannelConfigurer` has been renamed to `GrpcChannelBuilderCustomizer` to more accurately represent its purpose and be consistent with the server-side terminology. diff --git a/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfiguration.java b/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfiguration.java index 3f983dc..99daae7 100644 --- a/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfiguration.java +++ b/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfiguration.java @@ -30,7 +30,7 @@ import org.springframework.grpc.autoconfigure.client.GrpcClientProperties.NamedC import org.springframework.grpc.autoconfigure.common.codec.GrpcCodecConfiguration; import org.springframework.grpc.client.ChannelCredentialsProvider; import org.springframework.grpc.client.DefaultGrpcChannelFactory; -import org.springframework.grpc.client.GrpcChannelConfigurer; +import org.springframework.grpc.client.GrpcChannelBuilderCustomizer; import org.springframework.grpc.client.GrpcChannelFactory; import org.springframework.grpc.client.VirtualTargets; @@ -44,9 +44,9 @@ public class GrpcClientAutoConfiguration { @Bean @ConditionalOnMissingBean(GrpcChannelFactory.class) - public DefaultGrpcChannelFactory defaultGrpcChannelFactory(final List configurers, + public DefaultGrpcChannelFactory defaultGrpcChannelFactory(List customizers, ChannelCredentialsProvider credentials, GrpcClientProperties channels, SslBundles ignored) { - DefaultGrpcChannelFactory factory = new DefaultGrpcChannelFactory(configurers); + DefaultGrpcChannelFactory factory = new DefaultGrpcChannelFactory(customizers); factory.setCredentialsProvider(credentials); factory.setVirtualTargets(new NamedChannelVirtualTargets(channels)); return factory; @@ -60,7 +60,7 @@ public class GrpcClientAutoConfiguration { } @Bean - public GrpcChannelConfigurer baseGrpcChannelConfigurer(GrpcClientProperties channels) { + public GrpcChannelBuilderCustomizer baseGrpcChannelBuilderCustomizer(GrpcClientProperties channels) { return (authority, builder) -> { for (String name : channels.getChannels().keySet()) { if (authority.equals(name)) { @@ -101,13 +101,13 @@ public class GrpcClientAutoConfiguration { @ConditionalOnBean(CompressorRegistry.class) @Bean - GrpcChannelConfigurer compressionClientConfigurer(CompressorRegistry registry) { + GrpcChannelBuilderCustomizer compressionClientCustomizer(CompressorRegistry registry) { return (name, builder) -> builder.compressorRegistry(registry); } @ConditionalOnBean(DecompressorRegistry.class) @Bean - GrpcChannelConfigurer decompressionClientConfigurer(DecompressorRegistry registry) { + GrpcChannelBuilderCustomizer decompressionClientCustomizer(DecompressorRegistry registry) { return (name, builder) -> builder.decompressorRegistry(registry); } diff --git a/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfigurationTests.java b/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfigurationTests.java index c0d99e6..9284cdd 100644 --- a/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfigurationTests.java +++ b/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/client/GrpcClientAutoConfigurationTests.java @@ -35,7 +35,7 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.grpc.autoconfigure.client.GrpcClientAutoConfiguration.NamedChannelVirtualTargets; import org.springframework.grpc.client.ChannelCredentialsProvider; import org.springframework.grpc.client.DefaultGrpcChannelFactory; -import org.springframework.grpc.client.GrpcChannelConfigurer; +import org.springframework.grpc.client.GrpcChannelBuilderCustomizer; import org.springframework.grpc.client.GrpcChannelFactory; import io.grpc.Codec; @@ -91,27 +91,30 @@ class GrpcClientAutoConfigurationTests { } @Test - void baseChannelConfigurerAutoConfiguredWithHealthAsExpected() { + void baseChannelCustomizerAutoConfiguredWithHealthAsExpected() { this.contextRunner() .withPropertyValues("spring.grpc.client.channels.test.health.enabled=true", "spring.grpc.client.channels.test.health.service-name=my-service") .run((context) -> { - assertThat(context).getBean("baseGrpcChannelConfigurer", GrpcChannelConfigurer.class).isNotNull(); - var configurer = context.getBean("baseGrpcChannelConfigurer", GrpcChannelConfigurer.class); + assertThat(context).getBean("baseGrpcChannelBuilderCustomizer", GrpcChannelBuilderCustomizer.class) + .isNotNull(); + var customizer = context.getBean("baseGrpcChannelBuilderCustomizer", + GrpcChannelBuilderCustomizer.class); ManagedChannelBuilder builder = Mockito.mock(); - configurer.configure("test", builder); + customizer.customize("test", builder); Map healthCheckConfig = Map.of("healthCheckConfig", Map.of("serviceName", "my-service")); verify(builder).defaultServiceConfig(healthCheckConfig); }); } @Test - void baseChannelConfigurerAutoConfiguredWithoutHealthAsExpected() { + void baseChannelCustomizerAutoConfiguredWithoutHealthAsExpected() { this.contextRunner().run((context) -> { - assertThat(context).getBean("baseGrpcChannelConfigurer", GrpcChannelConfigurer.class).isNotNull(); - var configurer = context.getBean("baseGrpcChannelConfigurer", GrpcChannelConfigurer.class); + assertThat(context).getBean("baseGrpcChannelBuilderCustomizer", GrpcChannelBuilderCustomizer.class) + .isNotNull(); + var customizer = context.getBean("baseGrpcChannelBuilderCustomizer", GrpcChannelBuilderCustomizer.class); ManagedChannelBuilder builder = Mockito.mock(); - configurer.configure("test", builder); + customizer.customize("test", builder); verify(builder, never()).defaultServiceConfig(anyMap()); }); } @@ -122,18 +125,19 @@ class GrpcClientAutoConfigurationTests { // registry this.contextRunner() .withClassLoader(new FilteredClassLoader(Codec.class)) - .run((context) -> assertThat(context).getBean("compressionClientConfigurer", GrpcChannelConfigurer.class) + .run((context) -> assertThat(context) + .getBean("compressionClientCustomizer", GrpcChannelBuilderCustomizer.class) .isNull()); } @Test - void compressionConfigurerAutoConfiguredAsExpected() { + void compressionCustomizerAutoConfiguredAsExpected() { this.contextRunner().run((context) -> { - assertThat(context).getBean("compressionClientConfigurer", GrpcChannelConfigurer.class).isNotNull(); - var configurer = context.getBean("compressionClientConfigurer", GrpcChannelConfigurer.class); + assertThat(context).getBean("compressionClientCustomizer", GrpcChannelBuilderCustomizer.class).isNotNull(); + var customizer = context.getBean("compressionClientCustomizer", GrpcChannelBuilderCustomizer.class); var compressorRegistry = context.getBean(CompressorRegistry.class); ManagedChannelBuilder builder = Mockito.mock(); - configurer.configure("testChannel", builder); + customizer.customize("testChannel", builder); verify(builder).compressorRegistry(compressorRegistry); }); } @@ -144,18 +148,20 @@ class GrpcClientAutoConfigurationTests { // registry this.contextRunner() .withClassLoader(new FilteredClassLoader(Codec.class)) - .run((context) -> assertThat(context).getBean("decompressionClientConfigurer", GrpcChannelConfigurer.class) + .run((context) -> assertThat(context) + .getBean("decompressionClientCustomizer", GrpcChannelBuilderCustomizer.class) .isNull()); } @Test - void decompressionConfigurerAutoConfiguredAsExpected() { + void decompressionCustomizerAutoConfiguredAsExpected() { this.contextRunner().run((context) -> { - assertThat(context).getBean("decompressionClientConfigurer", GrpcChannelConfigurer.class).isNotNull(); - var configurer = context.getBean("decompressionClientConfigurer", GrpcChannelConfigurer.class); + assertThat(context).getBean("decompressionClientCustomizer", GrpcChannelBuilderCustomizer.class) + .isNotNull(); + var customizer = context.getBean("decompressionClientCustomizer", GrpcChannelBuilderCustomizer.class); var decompressorRegistry = context.getBean(DecompressorRegistry.class); ManagedChannelBuilder builder = Mockito.mock(); - configurer.configure("testChannel", builder); + customizer.customize("testChannel", builder); verify(builder).decompressorRegistry(decompressorRegistry); }); }