Add Builder to RSocketServiceProxyFactory

RSocketServiceProxyFactory now support programmatic initialization
through a builder, while bean-style initialization is deprecated.

Closes gh-29296
This commit is contained in:
rstoyanchev 2022-10-19 14:36:45 +01:00
parent bd59c7a691
commit d4f7484252
5 changed files with 360 additions and 98 deletions

View File

@ -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<RSocketServiceArgumentResolver> customArgumentResolvers;
@Nullable
private List<RSocketServiceArgumentResolver> 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<RSocketServiceArgumentResolver> 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<RSocketServiceArgumentResolver> 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.
* <p>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.
* <p>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<RSocketServiceArgumentResolver> initArgumentResolvers() {
List<RSocketServiceArgumentResolver> 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> S createClient(Class<S> serviceType) {
List<RSocketServiceMethod> 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 <S> RSocketServiceMethod createRSocketServiceMethod(Class<S> 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<RSocketServiceArgumentResolver> 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.
* <p>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.
* <p>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<RSocketServiceArgumentResolver> initArgumentResolvers() {
// Custom
List<RSocketServiceArgumentResolver> 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<RSocketServiceArgumentResolver> argumentResolvers;
@Nullable
private final StringValueResolver embeddedValueResolver;
private final ReactiveAdapterRegistry reactiveAdapterRegistry;
private final Duration blockTimeout;
public BuilderInitializedFactory(
RSocketRequester rsocketRequester, List<RSocketServiceArgumentResolver> 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> S createClient(Class<S> serviceType) {
List<RSocketServiceMethod> 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 <S> RSocketServiceMethod createRSocketServiceMethod(Class<S> 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<RSocketServiceArgumentResolver> customArgumentResolvers;
@Nullable
private List<RSocketServiceArgumentResolver> 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<RSocketServiceArgumentResolver> 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<RSocketServiceArgumentResolver> initArgumentResolvers() {
List<RSocketServiceArgumentResolver> 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> S createClient(Class<S> serviceType) {
List<RSocketServiceMethod> 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 <S> RSocketServiceMethod createRSocketServiceMethod(Class<S> 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);
}
}
}

View File

@ -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();

View File

@ -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();
}

View File

@ -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<HttpServiceArgumentResolver> 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.
* <p>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.
* <p>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.
* <p>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<HttpServiceArgumentResolver> argumentResolvers;
private final List<HttpServiceArgumentResolver> 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<HttpServiceArgumentResolver> initArgumentResolvers() {
List<HttpServiceArgumentResolver> resolvers = new ArrayList<>();
// Custom
if (this.argumentResolvers != null) {
resolvers.addAll(this.argumentResolvers);
}
List<HttpServiceArgumentResolver> 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);
}
}
}

View File

@ -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);
----