Abhinab Kanrar
Abhinab Kanrar

Reputation: 1552

Why is this CompletionStage code causing a compilation error?

I have two class;say A and B; both returning CompletionStage.
class B code:

class B {
    public CompletionStage<Optional<Map<String, Object>>> m1(SampleObject1 obj) {
        return CompletableFuture.supplyAsync(() -> dosomething(obj))
            .thenApplyAsync(results ->
                Optional.ofNullable((results.length == 1) ? results : null)
            );
    }
}

class A code:

class A {
    public CompletionStage<Optional<SampleObject2>> m2(Optional<DynamicForm> dynamicForm) {
        CompletionStage<DynamicForm> promiseOfFormData = CompletableFuture.supplyAsync(() -> dynamicForm.get());

        CompletionStage<Optional<Map<String, Object>>> c = promiseOfFormData.thenApplyAsync(
            data -> b.m1(new SampleObject1(data.get("key1"), data.get("key2")))
        );
        return something.....;
    }
}

However, it's throwing following error at runtime:

inference variable U has incompatible bounds
    equality constraints: java.util.Optional<java.util.Map<java.lang.String,java.lang.Object>>
    lower bounds: java.util.concurrent.CompletionStage<java.util.Optional<java.util.Map<java.lang.String,java.lang.Object>>>

What am I doing wrong here?

Upvotes: 2

Views: 1532

Answers (1)

Didier L
Didier L

Reputation: 20579

You have a problem with your return types:

b.m1(new SampleObject1(data.get("key1"), data.get("key2")))

is returning a CompletionStage<Optional<Map<String, Object>>> as from the method signature in B, so

data -> b.m1(new SampleObject1(data.get("key1"), data.get("key2")))

is of type Function<DynamicForm,CompletionStage<Optional<Map<String, Object>>>> and the following

promiseOfFormData.thenApplyAsync(
    data -> b.m1(new SampleObject1(data.get("key1"), data.get("key2")))
);

is thus of type CompletionStage<CompletionStage<Optional<Map<String, Object>>>> which is incompatible with the target type CompletionStage<Optional<Map<String, Object>>>. The error you have is in the computation of the bounds of the target type.

What you should do instead is probably use CompletionStage#thenComposeAsync, which is designed for functions that also return a CompletionStage:

CompletionStage<Optional<Map<String, Object>>> c = promiseOfFormData.thenComposeAsync(
    data -> b.m1(new SampleObject1(data.get("key1"), data.get("key2")))
);

Alternatively, you could rewrite m1 to not create a CompletionStage but just perform the computation, and then use it in a thenApplyAsync call as you were previously doing.

Upvotes: 2

Related Questions