From d4f7484252c2662028e6ddef5baa1af4c45be4f6 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 19 Oct 2022 14:36:45 +0100 Subject: [PATCH] Add Builder to RSocketServiceProxyFactory RSocketServiceProxyFactory now support programmatic initialization through a builder, while bean-style initialization is deprecated. Closes gh-29296 --- .../service/RSocketServiceProxyFactory.java | 390 +++++++++++++++--- .../RSocketServiceIntegrationTests.java | 4 +- .../service/RSocketServiceMethodTests.java | 5 +- .../invoker/HttpServiceProxyFactory.java | 56 ++- src/docs/asciidoc/rsocket.adoc | 3 +- 5 files changed, 360 insertions(+), 98 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java index 500e07045fb..832f4be2c89 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java @@ -51,68 +51,85 @@ import org.springframework.util.StringValueResolver; */ public final class RSocketServiceProxyFactory implements InitializingBean, EmbeddedValueResolverAware { - private final RSocketRequester rsocketRequester; + @Nullable + private final BuilderInitializedFactory builderInitializedFactory; @Nullable - private List customArgumentResolvers; - - @Nullable - private List argumentResolvers; - - @Nullable - private StringValueResolver embeddedValueResolver; - - private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); - - private Duration blockTimeout = Duration.ofSeconds(5); + private final BeanStyleFactory beanStyleFactory; /** * Create an instance with the underlying RSocketRequester to perform requests with. * @param rsocketRequester the requester to use + * @deprecated in favor of using the Builder to initialize the + * RSocketServiceProxyFactory instance. */ + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public RSocketServiceProxyFactory(RSocketRequester rsocketRequester) { - Assert.notNull(rsocketRequester, "RSocketRequester is required"); - this.rsocketRequester = rsocketRequester; + this.beanStyleFactory = new BeanStyleFactory(rsocketRequester); + this.builderInitializedFactory = null; + } + + private RSocketServiceProxyFactory( + RSocketRequester rsocketRequester, List argumentResolvers, + @Nullable StringValueResolver embeddedValueResolver, + ReactiveAdapterRegistry reactiveAdapterRegistry, Duration blockTimeout) { + + this.beanStyleFactory = null; + this.builderInitializedFactory = new BuilderInitializedFactory( + rsocketRequester, argumentResolvers, embeddedValueResolver, reactiveAdapterRegistry, blockTimeout); } /** * Register a custom argument resolver, invoked ahead of default resolvers. * @param resolver the resolver to add + * @deprecated in favor of using the Builder to initialize the + * RSocketServiceProxyFactory instance. */ + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void addCustomArgumentResolver(RSocketServiceArgumentResolver resolver) { - if (this.customArgumentResolvers == null) { - this.customArgumentResolvers = new ArrayList<>(); - } - this.customArgumentResolvers.add(resolver); + Assert.state(this.beanStyleFactory != null, "RSocketServiceProxyFactory was created through the builder"); + this.beanStyleFactory.addCustomArgumentResolver(resolver); } /** * Set the custom argument resolvers to use, ahead of default resolvers. * @param resolvers the resolvers to use + * @deprecated in favor of using the Builder to initialize the + * RSocketServiceProxyFactory instance. */ + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void setCustomArgumentResolvers(List resolvers) { - this.customArgumentResolvers = new ArrayList<>(resolvers); + Assert.state(this.beanStyleFactory != null, "RSocketServiceProxyFactory was created through the builder"); + this.beanStyleFactory.setCustomArgumentResolvers(resolvers); } /** * Set the StringValueResolver to use for resolving placeholders and * expressions in {@link RSocketExchange#value()}. * @param resolver the resolver to use + * @deprecated in favor of using the Builder to initialize the + * RSocketServiceProxyFactory instance. */ + @Deprecated(since = "6.0.0-RC2", forRemoval = true) @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { - this.embeddedValueResolver = resolver; + Assert.state(this.beanStyleFactory != null, "RSocketServiceProxyFactory was created through the builder"); + this.beanStyleFactory.setEmbeddedValueResolver(resolver); } /** * Set the {@link ReactiveAdapterRegistry} to use to support different * asynchronous types for RSocket service method return values. *

By default this is {@link ReactiveAdapterRegistry#getSharedInstance()}. + * @deprecated in favor of using the Builder to initialize the + * RSocketServiceProxyFactory instance. */ + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) { - this.reactiveAdapterRegistry = registry; + Assert.state(this.beanStyleFactory != null, "RSocketServiceProxyFactory was created through the builder"); + this.beanStyleFactory.setReactiveAdapterRegistry(registry); } /** @@ -120,36 +137,22 @@ public final class RSocketServiceProxyFactory implements InitializingBean, Embed * with a synchronous (blocking) method signature. *

By default this is 5 seconds. * @param blockTimeout the timeout value + * @deprecated in favor of using the Builder to initialize the + * RSocketServiceProxyFactory instance. */ + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void setBlockTimeout(Duration blockTimeout) { - this.blockTimeout = blockTimeout; + Assert.state(this.beanStyleFactory != null, "RSocketServiceProxyFactory was created through the builder"); + this.beanStyleFactory.setBlockTimeout(blockTimeout); } @Override + @Deprecated public void afterPropertiesSet() throws Exception { - this.argumentResolvers = initArgumentResolvers(); - } - - private List initArgumentResolvers() { - List resolvers = new ArrayList<>(); - - // Custom - if (this.customArgumentResolvers != null) { - resolvers.addAll(this.customArgumentResolvers); + if (this.beanStyleFactory != null) { + this.beanStyleFactory.afterPropertiesSet(); } - - // Annotation-based - resolvers.add(new PayloadArgumentResolver(this.reactiveAdapterRegistry, false)); - resolvers.add(new DestinationVariableArgumentResolver()); - - // Type-based - resolvers.add(new MetadataArgumentResolver()); - - // Fallback - resolvers.add(new PayloadArgumentResolver(this.reactiveAdapterRegistry, true)); - - return resolvers; } @@ -162,26 +165,138 @@ public final class RSocketServiceProxyFactory implements InitializingBean, Embed * @return the created proxy */ public S createClient(Class serviceType) { - - List serviceMethods = - MethodIntrospector.selectMethods(serviceType, this::isExchangeMethod).stream() - .map(method -> createRSocketServiceMethod(serviceType, method)) - .toList(); - - return ProxyFactory.getProxy(serviceType, new ServiceMethodInterceptor(serviceMethods)); + if (this.builderInitializedFactory != null) { + return this.builderInitializedFactory.createClient(serviceType); + } + else if (this.beanStyleFactory != null) { + return this.beanStyleFactory.createClient(serviceType); + } + else { + throw new IllegalStateException("Expected Builder initialized or Bean-style delegate"); + } } - private boolean isExchangeMethod(Method method) { - return AnnotatedElementUtils.hasAnnotation(method, RSocketExchange.class); + + /** + * Return an {@link RSocketServiceProxyFactory} builder, initialized with the + * given client. + */ + public static Builder builder(RSocketRequester requester) { + return new Builder().rsocketRequester(requester); } - private RSocketServiceMethod createRSocketServiceMethod(Class serviceType, Method method) { - Assert.notNull(this.argumentResolvers, - "No argument resolvers: afterPropertiesSet was not called"); + /** + * Return an {@link RSocketServiceProxyFactory} builder. + */ + public static Builder builder() { + return new Builder(); + } - return new RSocketServiceMethod( - method, serviceType, this.argumentResolvers, this.rsocketRequester, - this.embeddedValueResolver, this.reactiveAdapterRegistry, this.blockTimeout); + + /** + * Builder to create an {@link RSocketServiceProxyFactory}. + */ + public static final class Builder { + + @Nullable + private RSocketRequester rsocketRequester; + + private final List customArgumentResolvers = new ArrayList<>(); + + @Nullable + private StringValueResolver embeddedValueResolver; + + private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); + + @Nullable + private Duration blockTimeout = Duration.ofSeconds(5); + + private Builder() { + } + + /** + * Provide the requester to perform requests through. + * @param requester the requester to use + * @return the same builder instance + */ + public Builder rsocketRequester(RSocketRequester requester) { + this.rsocketRequester = requester; + return this; + } + + /** + * Register a custom argument resolver, invoked ahead of default resolvers. + * @param resolver the resolver to add + * @return the same builder instance + */ + public Builder customArgumentResolver(RSocketServiceArgumentResolver resolver) { + this.customArgumentResolvers.add(resolver); + return this; + } + + /** + * Set the {@link StringValueResolver} to use for resolving placeholders + * and expressions embedded in {@link RSocketExchange#value()}. + * @param resolver the resolver to use + * @return this same builder instance + */ + public Builder embeddedValueResolver(StringValueResolver resolver) { + this.embeddedValueResolver = resolver; + return this; + } + + /** + * Set the {@link ReactiveAdapterRegistry} to use to support different + * asynchronous types for HTTP service method return values. + *

By default this is {@link ReactiveAdapterRegistry#getSharedInstance()}. + * @return this same builder instance + */ + public Builder reactiveAdapterRegistry(ReactiveAdapterRegistry registry) { + this.reactiveAdapterRegistry = registry; + return this; + } + + /** + * Configure how long to wait for a response for an HTTP service method + * with a synchronous (blocking) method signature. + *

By default this is 5 seconds. + * @param blockTimeout the timeout value + * @return this same builder instance + */ + public Builder blockTimeout(Duration blockTimeout) { + this.blockTimeout = blockTimeout; + return this; + } + + /** + * Build the {@link RSocketServiceProxyFactory} instance. + */ + public RSocketServiceProxyFactory build() { + Assert.notNull(this.rsocketRequester, "RSocketRequester is required"); + + return new RSocketServiceProxyFactory( + this.rsocketRequester, initArgumentResolvers(), + this.embeddedValueResolver, this.reactiveAdapterRegistry, + (this.blockTimeout != null ? this.blockTimeout : Duration.ofSeconds(5))); + } + + private List initArgumentResolvers() { + + // Custom + List resolvers = new ArrayList<>(this.customArgumentResolvers); + + // Annotation-based + resolvers.add(new PayloadArgumentResolver(this.reactiveAdapterRegistry, false)); + resolvers.add(new DestinationVariableArgumentResolver()); + + // Type-based + resolvers.add(new MetadataArgumentResolver()); + + // Fallback + resolvers.add(new PayloadArgumentResolver(this.reactiveAdapterRegistry, true)); + + return resolvers; + } } @@ -214,4 +329,163 @@ public final class RSocketServiceProxyFactory implements InitializingBean, Embed } } + + /** + * Temporary class until bean-style initialization is removed. + */ + private static final class BuilderInitializedFactory { + + private final RSocketRequester rsocketRequester; + + private final List argumentResolvers; + + @Nullable + private final StringValueResolver embeddedValueResolver; + + private final ReactiveAdapterRegistry reactiveAdapterRegistry; + + private final Duration blockTimeout; + + + public BuilderInitializedFactory( + RSocketRequester rsocketRequester, List argumentResolvers, + @Nullable StringValueResolver embeddedValueResolver, + ReactiveAdapterRegistry reactiveAdapterRegistry, Duration blockTimeout) { + + this.rsocketRequester = rsocketRequester; + this.argumentResolvers = argumentResolvers; + this.embeddedValueResolver = embeddedValueResolver; + this.reactiveAdapterRegistry = reactiveAdapterRegistry; + this.blockTimeout = blockTimeout; + } + + + public S createClient(Class serviceType) { + + List serviceMethods = + MethodIntrospector.selectMethods(serviceType, this::isExchangeMethod).stream() + .map(method -> createRSocketServiceMethod(serviceType, method)) + .toList(); + + return ProxyFactory.getProxy(serviceType, new ServiceMethodInterceptor(serviceMethods)); + } + + private boolean isExchangeMethod(Method method) { + return AnnotatedElementUtils.hasAnnotation(method, RSocketExchange.class); + } + + private RSocketServiceMethod createRSocketServiceMethod(Class serviceType, Method method) { + Assert.notNull(this.argumentResolvers, + "No argument resolvers: afterPropertiesSet was not called"); + + return new RSocketServiceMethod( + method, serviceType, this.argumentResolvers, this.rsocketRequester, + this.embeddedValueResolver, this.reactiveAdapterRegistry, this.blockTimeout); + } + } + + + /** + * Temporary class to support bean-style initialization during deprecation period. + */ + private static final class BeanStyleFactory implements InitializingBean, EmbeddedValueResolverAware { + + private final RSocketRequester rsocketRequester; + + @Nullable + private List customArgumentResolvers; + + @Nullable + private List argumentResolvers; + + @Nullable + private StringValueResolver embeddedValueResolver; + + private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); + + private Duration blockTimeout = Duration.ofSeconds(5); + + + public BeanStyleFactory(RSocketRequester rsocketRequester) { + Assert.notNull(rsocketRequester, "RSocketRequester is required"); + this.rsocketRequester = rsocketRequester; + } + + + public void addCustomArgumentResolver(RSocketServiceArgumentResolver resolver) { + if (this.customArgumentResolvers == null) { + this.customArgumentResolvers = new ArrayList<>(); + } + this.customArgumentResolvers.add(resolver); + } + + public void setCustomArgumentResolvers(List resolvers) { + this.customArgumentResolvers = new ArrayList<>(resolvers); + } + + @Override + public void setEmbeddedValueResolver(StringValueResolver resolver) { + this.embeddedValueResolver = resolver; + } + + public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) { + this.reactiveAdapterRegistry = registry; + } + + public void setBlockTimeout(Duration blockTimeout) { + this.blockTimeout = blockTimeout; + } + + + @Override + public void afterPropertiesSet() { + this.argumentResolvers = initArgumentResolvers(); + } + + private List initArgumentResolvers() { + List resolvers = new ArrayList<>(); + + // Custom + if (this.customArgumentResolvers != null) { + resolvers.addAll(this.customArgumentResolvers); + } + + // Annotation-based + resolvers.add(new PayloadArgumentResolver(this.reactiveAdapterRegistry, false)); + resolvers.add(new DestinationVariableArgumentResolver()); + + // Type-based + resolvers.add(new MetadataArgumentResolver()); + + // Fallback + resolvers.add(new PayloadArgumentResolver(this.reactiveAdapterRegistry, true)); + + return resolvers; + } + + + public S createClient(Class serviceType) { + + List serviceMethods = + MethodIntrospector.selectMethods(serviceType, this::isExchangeMethod).stream() + .map(method -> createRSocketServiceMethod(serviceType, method)) + .toList(); + + return ProxyFactory.getProxy(serviceType, new ServiceMethodInterceptor(serviceMethods)); + } + + private boolean isExchangeMethod(Method method) { + return AnnotatedElementUtils.hasAnnotation(method, RSocketExchange.class); + } + + private RSocketServiceMethod createRSocketServiceMethod(Class serviceType, Method method) { + Assert.notNull(this.argumentResolvers, + "No argument resolvers: afterPropertiesSet was not called"); + + return new RSocketServiceMethod( + method, serviceType, this.argumentResolvers, this.rsocketRequester, + this.embeddedValueResolver, this.reactiveAdapterRegistry, this.blockTimeout); + } + } + } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketServiceIntegrationTests.java b/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketServiceIntegrationTests.java index 1f999db2f45..e192afd3fec 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketServiceIntegrationTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketServiceIntegrationTests.java @@ -75,9 +75,7 @@ class RSocketServiceIntegrationTests { .rsocketStrategies(context.getBean(RSocketStrategies.class)) .tcp("localhost", 7000); - RSocketServiceProxyFactory proxyFactory = new RSocketServiceProxyFactory(requester); - proxyFactory.afterPropertiesSet(); - + RSocketServiceProxyFactory proxyFactory = RSocketServiceProxyFactory.builder(requester).build(); serviceProxy = proxyFactory.createClient(Service.class); context.close(); diff --git a/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketServiceMethodTests.java b/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketServiceMethodTests.java index 905e64a73d1..3292e6f1dd9 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketServiceMethodTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketServiceMethodTests.java @@ -47,11 +47,10 @@ public class RSocketServiceMethodTests { @BeforeEach - public void setUp() throws Exception { + public void setUp() { this.rsocket = new TestRSocket(); RSocketRequester requester = RSocketRequester.wrap(this.rsocket, TEXT_PLAIN, TEXT_PLAIN, RSocketStrategies.create()); - this.proxyFactory = new RSocketServiceProxyFactory(requester); - this.proxyFactory.afterPropertiesSet(); + this.proxyFactory = RSocketServiceProxyFactory.builder(requester).build(); } diff --git a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java index a3b0c49c2d1..7e23fb4c408 100644 --- a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java +++ b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java @@ -64,10 +64,10 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded /** * Create an instance with the underlying HTTP client to use. * @param clientAdapter an adapter for the client - * @deprecated as of 6.0 RC1 in favor of using the Builder to initialize - * the HttpServiceProxyFactory instance. + * @deprecated in favor of using the Builder to initialize the + * HttpServiceProxyFactory instance. */ - @Deprecated(since = "6.0.0-RC1", forRemoval = true) + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public HttpServiceProxyFactory(HttpClientAdapter clientAdapter) { this.beanStyleFactory = new BeanStyleFactory(clientAdapter); this.builderInitializedFactory = null; @@ -87,10 +87,10 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded /** * Register a custom argument resolver, invoked ahead of default resolvers. * @param resolver the resolver to add - * @deprecated as of 6.0 RC1 in favor of using the Builder to initialize - * the HttpServiceProxyFactory instance. + * @deprecated in favor of using the Builder to initialize the + * HttpServiceProxyFactory instance. */ - @Deprecated(since = "6.0.0-RC1", forRemoval = true) + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void addCustomArgumentResolver(HttpServiceArgumentResolver resolver) { Assert.state(this.beanStyleFactory != null, "HttpServiceProxyFactory was created through the builder"); this.beanStyleFactory.addCustomArgumentResolver(resolver); @@ -99,10 +99,10 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded /** * Set the custom argument resolvers to use, ahead of default resolvers. * @param resolvers the resolvers to use - * @deprecated as of 6.0 RC1 in favor of using the Builder to initialize - * the HttpServiceProxyFactory instance. + * @deprecated in favor of using the Builder to initialize the + * HttpServiceProxyFactory instance. */ - @Deprecated(since = "6.0.0-RC1", forRemoval = true) + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void setCustomArgumentResolvers(List resolvers) { Assert.state(this.beanStyleFactory != null, "HttpServiceProxyFactory was created through the builder"); this.beanStyleFactory.setCustomArgumentResolvers(resolvers); @@ -112,10 +112,10 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded * Set the {@link ConversionService} to use where input values need to * be formatted as Strings. *

By default this is {@link DefaultFormattingConversionService}. - * @deprecated as of 6.0 RC1 in favor of using the Builder to initialize - * the HttpServiceProxyFactory instance. + * @deprecated in favor of using the Builder to initialize the + * HttpServiceProxyFactory instance. */ - @Deprecated(since = "6.0.0-RC1", forRemoval = true) + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void setConversionService(ConversionService conversionService) { Assert.state(this.beanStyleFactory != null, "HttpServiceProxyFactory was created through the builder"); this.beanStyleFactory.setConversionService(conversionService); @@ -125,10 +125,10 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded * Set the StringValueResolver to use for resolving placeholders and * expressions in {@link HttpExchange#url()}. * @param resolver the resolver to use - * @deprecated as of 6.0 RC1 in favor of using the Builder to initialize - * an HttpServiceProxyFactory instance. + * @deprecated in favor of using the Builder to initialize the + * HttpServiceProxyFactory instance. */ - @Deprecated(since = "6.0.0-RC1", forRemoval = true) + @Deprecated(since = "6.0.0-RC2", forRemoval = true) @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { Assert.state(this.beanStyleFactory != null, "HttpServiceProxyFactory was created through the builder"); @@ -139,10 +139,10 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded * Set the {@link ReactiveAdapterRegistry} to use to support different * asynchronous types for HTTP service method return values. *

By default this is {@link ReactiveAdapterRegistry#getSharedInstance()}. - * @deprecated as of 6.0 RC1 in favor of using the Builder to initialize - * an HttpServiceProxyFactory instance. + * @deprecated in favor of using the Builder to initialize the + * HttpServiceProxyFactory instance. */ - @Deprecated(since = "6.0.0-RC1", forRemoval = true) + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) { Assert.state(this.beanStyleFactory != null, "HttpServiceProxyFactory was created through the builder"); this.beanStyleFactory.setReactiveAdapterRegistry(registry); @@ -153,10 +153,10 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded * with a synchronous (blocking) method signature. *

By default this is 5 seconds. * @param blockTimeout the timeout value - * @deprecated as of 6.0 RC1 in favor of using the Builder to initialize - * an HttpServiceProxyFactory instance. + * @deprecated in favor of using the Builder to initialize the + * HttpServiceProxyFactory instance. */ - @Deprecated(since = "6.0.0-RC1", forRemoval = true) + @Deprecated(since = "6.0.0-RC2", forRemoval = true) public void setBlockTimeout(Duration blockTimeout) { Assert.state(this.beanStyleFactory != null, "HttpServiceProxyFactory was created through the builder"); this.beanStyleFactory.setBlockTimeout(blockTimeout); @@ -216,8 +216,7 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded @Nullable private HttpClientAdapter clientAdapter; - @Nullable - private List argumentResolvers; + private final List customArgumentResolvers = new ArrayList<>(); @Nullable private ConversionService conversionService; @@ -249,8 +248,7 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded * @return this same builder instance */ public Builder customArgumentResolver(HttpServiceArgumentResolver resolver) { - this.argumentResolvers = (this.argumentResolvers != null ? this.argumentResolvers : new ArrayList<>()); - this.argumentResolvers.add(resolver); + this.customArgumentResolvers.add(resolver); return this; } @@ -312,12 +310,9 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded } private List initArgumentResolvers() { - List resolvers = new ArrayList<>(); // Custom - if (this.argumentResolvers != null) { - resolvers.addAll(this.argumentResolvers); - } + List resolvers = new ArrayList<>(this.customArgumentResolvers); ConversionService service = (this.conversionService != null ? this.conversionService : new DefaultFormattingConversionService()); @@ -336,7 +331,6 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded return resolvers; } - } @@ -420,7 +414,6 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded method, serviceType, this.argumentResolvers, this.clientAdapter, this.embeddedValueResolver, this.reactiveAdapterRegistry, this.blockTimeout); } - } @@ -536,7 +529,6 @@ public final class HttpServiceProxyFactory implements InitializingBean, Embedded method, serviceType, this.argumentResolvers, this.clientAdapter, this.embeddedValueResolver, this.reactiveAdapterRegistry, this.blockTimeout); } - } } diff --git a/src/docs/asciidoc/rsocket.adoc b/src/docs/asciidoc/rsocket.adoc index 03cae3a5f0a..dbdd05c558d 100644 --- a/src/docs/asciidoc/rsocket.adoc +++ b/src/docs/asciidoc/rsocket.adoc @@ -935,8 +935,7 @@ Two, create a proxy that will perform the declared RSocket exchanges: [source,java,indent=0,subs="verbatim,quotes"] ---- RSocketRequester requester = ... ; - RSocketServiceProxyFactory factory = new RSocketServiceProxyFactory(requester); - factory.afterPropertiesSet(); + RSocketServiceProxyFactory factory = RSocketServiceProxyFactory.builder(requester).build(); RepositoryService service = factory.createClient(RadarService.class); ----