Open
Description
I suggest adding support for CompletableFuture
and CompletionStage
as a valid return type for methods in Spring client interfaces backed by RestClient
and RestClientAdapter
.
It would be great to provide the ExecutorService
when creating the adapter or maybe leverage Async
annotation
Example
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestClient;
import org.springframework.web.service.annotation.GetExchange;
import org.springframework.web.service.annotation.PostExchange;
import org.springframework.web.service.annotation.RequestBody;
import org.springframework.web.service.annotation.PathVariable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
public interface MyApiClient {
@GetExchange("/users/{id}")
CompletableFuture<User> getUser(@PathVariable int id);
@PostExchange("/users")
CompletableFuture<ResponseEntity<User>> createUser(@RequestBody User user);
@GetExchange("/items")
CompletableFuture<List<Item>> getAllItems();
}
@Configuration
public class ClientConfig {
@Bean
public MyApiClient myApiClient(RestClient.Builder restClientBuilder) {
RestClient restClient = restClientBuilder.baseUrl("https://api.example.com/").build();
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(RestClientAdapter.forClient(restClient)).build();
return factory.createClient(MyApiClient.class);
}
}
@Service
public class MyService {
private final MyApiClient apiClient;
public MyService(MyApiClient apiClient) {
this.apiClient = apiClient;
}
public void processUser(int userId) {
apiClient.getUser(userId)
.thenAccept(user -> System.out.println("Retrieved user: " + user))
.exceptionally(ex -> {
System.err.println("Error fetching user: " + ex.getMessage());
return null;
});
}
}