Skip to content

Commit d1e279f

Browse files
committed
Add reference docs for HTTP Service config
Closes gh-34912
1 parent 81626b0 commit d1e279f

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

framework-docs/modules/ROOT/pages/integration/rest-clients.adoc

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,3 +1130,139 @@ For more details and options such as suppressing error status codes, see the ref
11301130
documentation for each client, as well as the Javadoc of `defaultStatusHandler` in
11311131
`RestClient.Builder` or `WebClient.Builder`, and the `setErrorHandler` of `RestTemplate`.
11321132

1133+
1134+
1135+
[[rest-http-interface-group-config]]
1136+
=== HTTP Interface Groups
1137+
1138+
It's trivial to create client proxies with `HttpServiceProxyFactory`, but to have them
1139+
declared as beans leads to repetitive configuration. You may also have multiple
1140+
target hosts, and therefore multiple clients to configure, and even more client proxy
1141+
beans to create.
1142+
1143+
To make it easier to work with interface clients at scale the Spring Framework provides
1144+
dedicated configuration support. It lets applications focus on identifying HTTP Services
1145+
by group, and customizing the client for each group, while the framework transparently
1146+
creates a registry of client proxies, and declares each proxy as a bean.
1147+
1148+
An HTTP Service group is simply a set of interfaces that share the same client setup and
1149+
`HttpServiceProxyFactory` instance to create proxies. Typically, that means one group per
1150+
host, but you can have more than one group for the same target host in case the
1151+
underlying client needs to be configured differently.
1152+
1153+
One way to declare HTTP Service groups is via `@ImportHttpServices` annotations in
1154+
`@Configuration` classes as shown below:
1155+
1156+
[source,java,indent=0,subs="verbatim,quotes"]
1157+
----
1158+
@Configuration
1159+
@ImportHttpServices(group = "echo", types = {EchoServieA.class, EchoServiceB.class}) // <1>
1160+
@ImportHttpServices(group = "greeting", basePackageClasses = GreetServiceA.class) // <2>
1161+
public class ClientConfig {
1162+
}
1163+
1164+
----
1165+
<1> Manually list interfaces for group "echo"
1166+
<2> Detect interfaces for group "greeting" under a base package
1167+
1168+
It is also possible to declare groups programmatically by creating an HTTP Service
1169+
registrar and then importing it:
1170+
1171+
[source,java,indent=0,subs="verbatim,quotes"]
1172+
----
1173+
public class MyHttpServiceRegistrar extends AbstractHttpServiceRegistrar { // <1>
1174+
1175+
@Override
1176+
protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata metadata) {
1177+
registry.forGroup("echo").register(EchoServiceA.class, EchoServiceB.class); // <2>
1178+
registry.forGroup("greeting").detectInBasePackages(GreetServiceA.class); // <3>
1179+
}
1180+
}
1181+
1182+
@Configuration
1183+
@Import(MyHttpServiceRegistrar.class) // <4>
1184+
public class ClientConfig {
1185+
}
1186+
1187+
----
1188+
<1> Create extension class of `AbstractHttpServiceRegistrar`
1189+
<2> Manually list interfaces for group "echo"
1190+
<3> Detect interfaces for group "greeting" under a base package
1191+
<4> Import the registrar
1192+
1193+
TIP: You can mix and match `@ImportHttpService` annotations with programmatic registrars,
1194+
and you can spread the imports across multiple configuration classes. All imports
1195+
contribute collaboratively the same, shared `HttpServiceProxyRegistry` instance.
1196+
1197+
Once HTTP Service groups are declared, add an `HttpServiceGroupConfigurer` bean to
1198+
customize the client for each group. For example:
1199+
1200+
[source,java,indent=0,subs="verbatim,quotes"]
1201+
----
1202+
@Configuration
1203+
@ImportHttpServices(group = "echo", types = {EchoServiceA.class, EchoServiceB.class})
1204+
@ImportHttpServices(group = "greeting", basePackageClasses = GreetServiceA.class)
1205+
public class ClientConfig {
1206+
1207+
@Bean
1208+
public RestClientHttpServiceGroupConfigurer groupConfigurer() {
1209+
return groups -> {
1210+
// configure client for group "echo"
1211+
groups.filterByName("echo").forEachClient((group, clientBuilder) -> ...);
1212+
1213+
// configure the clients for all groups
1214+
groups.forEachClient((group, clientBuilder) -> ...);
1215+
1216+
// configure client and proxy factory for each group
1217+
groups.forEachGroup((group, clientBuilder, factoryBuilder) -> ...);
1218+
};
1219+
}
1220+
}
1221+
----
1222+
1223+
TIP: Spring Boot uses an `HttpServiceGroupConfigurer` to add support for client properties
1224+
by HTTP Service group, Spring Security to add OAuth support, and Spring Cloud to add load
1225+
balancing.
1226+
1227+
As a result of the above, each client proxy is available as a bean that you can
1228+
conveniently autowire by type:
1229+
1230+
[source,java,indent=0,subs="verbatim,quotes"]
1231+
----
1232+
@RestController
1233+
public class EchoController {
1234+
1235+
private final EchoService echoService;
1236+
1237+
public EchoController(EchoService echoService) {
1238+
this.echoService = echoService;
1239+
}
1240+
1241+
// ...
1242+
}
1243+
----
1244+
1245+
However, if there are multiple client proxies of the same type, e.g. the same interface
1246+
in multiple groups, then there is no unique bean of that type, and you cannot autowire by
1247+
type only. For such cases, you can work directly with the `HttpServiceProxyRegistry` that
1248+
holds all proxies, and obtain the ones you need by group:
1249+
1250+
[source,java,indent=0,subs="verbatim,quotes"]
1251+
----
1252+
@RestController
1253+
public class EchoController {
1254+
1255+
private final EchoService echoService1;
1256+
1257+
private final EchoService echoService2;
1258+
1259+
public EchoController(HttpServiceProxyRegistry registry) {
1260+
this.echoService1 = registry.getClient("echo1", EchoService.class); // <1>
1261+
this.echoService2 = registry.getClient("echo2", EchoService.class); // <2>
1262+
}
1263+
1264+
// ...
1265+
}
1266+
----
1267+
<1> Access the `EchoService` client proxy for group "echo1"
1268+
<2> Access the `EchoService` client proxy for group "echo2"

0 commit comments

Comments
 (0)