'Easy Type erasure? of return type CompletableFuture lambda chain

Java says I'm returning one type, but I thought I was returning the one on Line 6.

On Line 5:

The method thenApply(Function<? super Integer,? extends U>) in the type CompletableFuture<Integer> is not applicable for the 
 arguments ((<no type> response) -> {})

If I uncomment Line 6, it compiles, but that's because returns a null CompletableFuture. In other words, the type HttpResponse got erased from the CompletableFuture generic class.

This is a reduced snippet of what I'm trying to do, which is to implement retry logic in an async way in a Java 11 application. I'd like the thenApply logic to return CompletableFuture<HttpResponse> which I'll then wrap into retry logic.

import java.util.concurrent.CompletableFuture;

public class StackOverflow {
    
    public static CompletableFuture<Integer> sendAsync(Integer response) {
        return CompletableFuture.completedFuture(response);
    }
    
    public static void main(String args[]){ 
        CompletableFuture<Integer> aFuture = 
                sendAsync(200)
                .thenApply(response -> { // Line 5
                    CompletableFuture<Integer> result = null; // Line 6
                    if (response >= 200 && response < 300) {
                        result = CompletableFuture.supplyAsync(() -> {
                            return response;
                        });
                    } else {
                        throw new RuntimeException();
                    };
//                  return null;  
                 });

    }
}

Thanks, Woodsman



Solution 1:[1]

For anyone else suffering with this:

As the code was written above, the thenApply did not return CompletableFuture, but rather CompletableFuture<CompleteableFuture>. To flatten this, I changed thenApply to thenCompose. This yields a type CompleteableFuture.

In the message:

The method thenApply(Function<? super Integer,? extends U>) in the type CompletableFuture<Integer> is not applicable for the 
 arguments ((<no type> response) -> {})

The argument Function<? super Integer,? extends U> does not mean what I originally thought. This somewhat Perl like expression means supply a Lambda function which takes one argument that extends or is an Integer, and return not an unknown or void. Instead the U means return a somewhat more complex type, or a nested type.

import java.util.concurrent.CompletableFuture;

public class StackOverflow {
    
    public static CompletableFuture<Integer> sendAsync(Integer response) {
        return CompletableFuture.completedFuture(response);
    }
    
    public static void main(String args[]){ 
        CompletableFuture<Integer> aFuture = 
                sendAsync(200)
                .thenCompose(response -> { // Line 5
                    CompletableFuture<Integer> result = null; // Line 6
                    if (response >= 200 && response < 300) {
                        result = CompletableFuture.supplyAsync(() -> {
                            return response;
                        });
                    } else {
                        throw new RuntimeException();
                    };
                    return result;  
                 });

    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Woodsman