Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callback with CompletableFuture

I'm trying to create a really simple callback using some Strings. The IDE's code sense is is moaning about an unchecked call to exceptionally. Can anyone give me a fix for this? The idea in the end is to wrap a network call so that the promised result is returned and I can tack on additional functions as needed.

import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class FuturesTest {

    public static void main(String[] args) throws Exception {
        new FuturesTest().go();
    }

    private void go() throws ExecutionException, InterruptedException {
        CompletableFuture.supplyAsync(new MakesANetworkCall())
                .whenComplete(new BiConsumer<String, String>() {
                    @Override
                    public void accept(String result, String s) {
                        System.out.println(result.toString());
                    }
                })
                .exceptionally(new Function<Exception, Exception>() {
                                   @Override
                                   public Exception apply(Exception e) {
                                       e.printStackTrace();
                                       return e;
                                   }
                               }
                ).thenApplyAsync(new Function<String, String>() {
                    @Override
                    public String apply(String o) {
                        System.out.println("Last action of all!");
                        return null;
                    }
                });

        System.out.println("Main thread will sleep");
        Thread.sleep(2500);
        System.out.println("Program over");
    }

    class MakesANetworkCall implements Supplier {

        @Override
        public String get() {
            try {
                System.out.println("Ground control to Major Tom");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            int i = 2/0;
            return new String("Major Tom reporting!");
        }
    }
}
like image 932
wax_lyrical Avatar asked Dec 05 '22 19:12

wax_lyrical


2 Answers

First of all, your class MakesANetworkCall implements the raw type Supplier instead of Supplier<String>. This will effectively disable the type checking and hide all errors you made, so it’s not the single warning you should worry about, as that’s not the only thing wrong in your code:

  • The BiConsumer passed to whenComplete should be able to consume a Throwable as its second argument.

  • The Function passed to exceptionally should consume a Throwable and return an alternative result.

Further, you are invoking a static method using the expression new CompletableFuture<String>() as its target and you have an obsolete string creation expression as new String("Major Tom reporting!") where the simple constant "Major Tom reporting!" will do. Generally, you seem to try to always use an inappropriate method, i.e. one designed to consume things you don’t use or one for supplying a value where you don’t have one. Consider this:

CompletableFuture.supplyAsync(new MakesANetworkCall())
    .thenAccept(result -> System.out.println(result))
    .exceptionally(e -> { e.printStackTrace(); return null;})
    .thenRun(()->System.out.println("Last action of all!"));

This does what seems to be your intention. If you ensure that your MakesANetworkCall correctly implements Supplier<String>, this should compile without any warnings.

like image 176
Holger Avatar answered Dec 24 '22 10:12

Holger


Your core issue is with class MakesANetworkCall implements Supplier {. This is using raw types and therefore hides further problems. Fix that to class MakesANetworkCall implements Supplier<String> { and fix all ensuing issues and you get:

    CompletableFuture.supplyAsync(new MakesANetworkCall())
            // Not <String, String>
            .whenComplete(new BiConsumer<String, Throwable>() {
                @Override
                public void accept(String result, Throwable t) {
                    System.out.println(result);
                }
            })
            // Not <Exception,Exception>
            .exceptionally(new Function<Throwable, String>() {
                @Override
                public String apply(Throwable t) {
                    t.printStackTrace();
                    // Must return a Streing
                    return t.getMessage();
                }
            }
            ).thenApplyAsync(new Function<String, String>() {
                @Override
                public String apply(String o) {
                    System.out.println("Last action of all!");
                    return null;
                }
            });
like image 42
OldCurmudgeon Avatar answered Dec 24 '22 09:12

OldCurmudgeon