Skip to content

Add Support to CompletableFuture as return type in Spring interfaces clients with RestClient #34748

Open
@ne3ma-ibraheem

Description

@ne3ma-ibraheem

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: webIssues in web modules (web, webmvc, webflux, websocket)status: waiting-for-triageAn issue we've not yet triaged or decided on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions