Option to supply client builder in HttpServiceGroupConfigurer

Closes gh-35707
This commit is contained in:
rstoyanchev
2025-11-06 11:58:37 +00:00
parent 6dd40a0252
commit 09105eb7b2
3 changed files with 104 additions and 42 deletions
@@ -64,20 +64,30 @@ public interface HttpServiceGroupConfigurer<CB> extends Ordered {
Groups<CB> filter(Predicate<HttpServiceGroup> predicate);
/**
* Configure the client builder for each
* {@link #filter(Predicate) filtered} group.
* Callback to customize the client builder for every group matched by
* the specified name or predicate filters, or to all groups
* if no filters are specified.
*/
void forEachClient(ClientCallback<CB> callback);
/**
* Configure the {@code HttpServiceProxyFactory} for each
* {@link #filter(Predicate) filtered} group.
* Callback to supply the client builder for every group matched by
* the specified name or predicate filters, or to all groups
* if no filters are specified.
*/
void forEachClient(InitializingClientCallback<CB> callback);
/**
* Callback to customize the proxy factory for every group matched by
* the specified name or predicate filters, or to all groups
* if no filters are specified.
*/
void forEachProxyFactory(ProxyFactoryCallback callback);
/**
* Configure the client builder and {@code HttpServiceProxyFactory} for each
* {@link #filter(Predicate) filtered} group.
* Callback to customize the client builder and the proxy factory for
* every group matched by the specified name or predicate filters,
* or to all groups if no filters are specified.
*/
void forEachGroup(GroupCallback<CB> callback);
}
@@ -94,6 +104,17 @@ public interface HttpServiceGroupConfigurer<CB> extends Ordered {
}
/**
* Callback to provide the client builder rather than customize it.
* @param <CB> the type of client builder, i.e. {@code RestClient} or {@code WebClient} builder.
*/
@FunctionalInterface
interface InitializingClientCallback<CB> {
CB initClient(HttpServiceGroup group);
}
/**
* Callback to configure the {@code HttpServiceProxyFactory} for a given group.
*/
@@ -131,16 +131,16 @@ public final class HttpServiceProxyRegistryFactoryBean
private static class GroupAdapterInitializer {
private static final String REST_CLIENT_HTTP_SERVICE_GROUP_ADAPTER = "org.springframework.web.client.support.RestClientHttpServiceGroupAdapter";
private static final String REST_CLIENT_HTTP_SERVICE_GROUP_ADAPTER =
"org.springframework.web.client.support.RestClientHttpServiceGroupAdapter";
private static final String WEB_CLIENT_HTTP_SERVICE_GROUP_ADAPTER = "org.springframework.web.reactive.function.client.support.WebClientHttpServiceGroupAdapter";
private static final String WEB_CLIENT_HTTP_SERVICE_GROUP_ADAPTER =
"org.springframework.web.reactive.function.client.support.WebClientHttpServiceGroupAdapter";
static Map<HttpServiceGroup.ClientType, HttpServiceGroupAdapter<?>> initGroupAdapters() {
Map<HttpServiceGroup.ClientType, HttpServiceGroupAdapter<?>> map = new LinkedHashMap<>(2);
addGroupAdapter(map, HttpServiceGroup.ClientType.REST_CLIENT, REST_CLIENT_HTTP_SERVICE_GROUP_ADAPTER);
addGroupAdapter(map, HttpServiceGroup.ClientType.WEB_CLIENT, WEB_CLIENT_HTTP_SERVICE_GROUP_ADAPTER);
return map;
}
@@ -167,14 +167,13 @@ public final class HttpServiceProxyRegistryFactoryBean
private final HttpServiceGroupAdapter<?> groupAdapter;
private final Object clientBuilder;
private @Nullable Object clientBuilder;
private final HttpServiceProxyFactory.Builder proxyFactoryBuilder = HttpServiceProxyFactory.builder();
ConfigurableGroup(HttpServiceGroup group) {
this.group = group;
this.groupAdapter = getGroupAdapter(group.clientType());
this.clientBuilder = this.groupAdapter.createClientBuilder();
}
private static HttpServiceGroupAdapter<?> getGroupAdapter(HttpServiceGroup.ClientType clientType) {
@@ -191,32 +190,39 @@ public final class HttpServiceProxyRegistryFactoryBean
return this.group;
}
@SuppressWarnings("unchecked")
public <CB> void applyClientCallback(HttpServiceGroupConfigurer.ClientCallback<CB> callback) {
callback.withClient(this.group, (CB) this.clientBuilder);
callback.withClient(this.group, getClientBuilder());
}
public <CB> void applyClientCallback(HttpServiceGroupConfigurer.InitializingClientCallback<CB> callback) {
Assert.state(this.clientBuilder == null, "Client builder already initialized");
this.clientBuilder = callback.initClient(this.group);
}
public void applyProxyFactoryCallback(HttpServiceGroupConfigurer.ProxyFactoryCallback callback) {
callback.withProxyFactory(this.group, this.proxyFactoryBuilder);
}
@SuppressWarnings("unchecked")
public <CB> void applyGroupCallback(HttpServiceGroupConfigurer.GroupCallback<CB> callback) {
callback.withGroup(this.group, (CB) this.clientBuilder, this.proxyFactoryBuilder);
callback.withGroup(this.group, getClientBuilder(), this.proxyFactoryBuilder);
}
@SuppressWarnings("unchecked")
private <CB> CB getClientBuilder() {
if (this.clientBuilder == null) {
this.clientBuilder = this.groupAdapter.createClientBuilder();
}
return (CB) this.clientBuilder;
}
public Map<Class<?>, Object> createProxies() {
Map<Class<?>, Object> map = new LinkedHashMap<>(this.group.httpServiceTypes().size());
HttpServiceProxyFactory factory = this.proxyFactoryBuilder.exchangeAdapter(initExchangeAdapter()).build();
HttpExchangeAdapter adapter = this.groupAdapter.createExchangeAdapter(getClientBuilder());
HttpServiceProxyFactory factory = this.proxyFactoryBuilder.exchangeAdapter(adapter).build();
this.group.httpServiceTypes().forEach(type -> map.put(type, factory.createClient(type)));
return map;
}
@SuppressWarnings("unchecked")
private <CB> HttpExchangeAdapter initExchangeAdapter() {
return ((HttpServiceGroupAdapter<CB>) this.groupAdapter).createExchangeAdapter((CB) this.clientBuilder);
}
@Override
public String toString() {
return getClass().getSimpleName() + "[name=" + name() + "]";
@@ -258,6 +264,11 @@ public final class HttpServiceProxyRegistryFactoryBean
filterAndReset().forEach(group -> group.applyClientCallback(callback));
}
@Override
public void forEachClient(HttpServiceGroupConfigurer.InitializingClientCallback<CB> callback) {
filterAndReset().forEach(group -> group.applyClientCallback(callback));
}
@Override
public void forEachProxyFactory(HttpServiceGroupConfigurer.ProxyFactoryCallback callback) {
filterAndReset().forEach(group -> group.applyProxyFactoryCallback(callback));