class: center, middle

# Future & CompletionStage

.byline[ *Will Billingsley, CC-BY* ]

---

## Why Futures?

Sometimes we don't want to wait for a result

* Long-running task in a UI framework

* Network call to another computer

* Waiting for user input

---

## Threads in Java

```java
new Thread(() -> {
    // Do something
}).start();
```

---

## Thread blocking example

* Most UI toolkits only have one UI thread
* If you do something long-running in an event-handler, it blocks the thread and freezes the UI

---

## A simple app

```java
public class Main extends Application {
    volatile double h = 0;
    volatile double rot = 0;

    @Override
    public void start(Stage primaryStage) throws Exception{
        Rectangle r = new Rectangle(200,200);
        Button b = new Button("Long task!");
        VBox vBox = new VBox(r, b);
        Scene scene = new Scene(vBox);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
```

This shows a black rectangle, sitting above a button

---

## Let's make it spin the rectangle

```java
TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        h = (h + 1) % 255;
        rot = (rot + 3) % 360;

        Platform.runLater(() -> {
            r.setFill(Color.hsb(h, 1, 1));
            r.setRotate(rot);
        });
    }
};
Timer t = new Timer();
t.schedule(timerTask, 1000/60, 1000/60);
```

---

## Now let's do something long when you press the button

```java
b.setOnAction((evt) -> {
    try {
        Thread.sleep(10000);
    } catch (Exception ex) {
        //
    }
});
```

When we press the button, the rectangle stops spinning

---

## What's happening...

* Our timer is still working (we can put in a println to check), because it is running on a different thread

* But the *UI thread* is busy (sleeping) for 10 seconds, so can't repaint the screen or react to any more button presses

---

## Let's fix it 

```java
b.setOnAction((evt) -> {
    new Thread(() -> {
      try {
        Thread.sleep(10000);
      } catch (Exception ex) {
        //
      }
    }).start();
});
```

Now the "long running task" happens on a different thread (not the UI thread) and doesn't block the UI

---

## Thread exhaustion

![Impressory pic](cosc250/impressory.png)

---

## Communicating between threads

Let's take another look at this code...

```java
TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        h = (h + 1) % 255;
        rot = (rot + 3) % 360;

        Platform.runLater(() -> {
            r.setFill(Color.hsb(h, 1, 1));
            r.setRotate(rot);
        });
    }
};
Timer t = new Timer();
t.schedule(timerTask, 1000/60, 1000/60);
```


---

## Communicating between threads

In our Java code, the TimerTask runs on its own thread. But the instructions to update the rectangle have to be put *back on the UI thread* because they modify the UI state.

```java
Platform.runLater(() -> {
    r.setFill(Color.hsb(h, 1, 1));
    r.setRotate(rot);
});
```

This is possible because the UI thread has a queue of tasks, and goes back to check it regularly.

ie, this communication isn't built into Threads, it's just that the code that is *running on the UI thread* was written to look in a queue for tasks to do.

(Platform.runLater is a method from the javafx packages)

---

## An observation

We've talked about concurrency in Java, but it's all been closely tied to *how concurrency is implemented*.

It would be nice to be able to talk just about the tasks. And to be able to compose them as easily as we can compose functions.

---

## Futures

`Future`s let us talk about *a computation that will complete at some point in the future*.

* Suppose we have a box   `[   ]`

--

* It will receive a value  `[ 7 ]`

--

* But I don't know when  `[ ? ]`

--

*When the box has a value, print it out*

---

## Futures

```scala
val myFuture:Future[Int] = longRunningTask()
myFuture.onSuccess({ case x => println(x) })
```

---

## Java has Futures too...

* Java has had a class called `Future` since Java 5...
  ... but it doesn't have the methods we want (onSuccess, etc)
  
* Java 8 introduced `CompletionStage`

---

## CompletionStage

> A stage of a possibly asynchronous computation, that performs an action or computes a value when another CompletionStage completes. A stage completes upon termination of its computation, but this may in turn trigger other dependent stages.
 
 ```java
 stage.thenApply(x -> square(x))
   .thenAccept(x -> System.out.print(x))
   .thenRun(() -> System.out.println())
 ```

Roughly the same as the Scala version, but named differently

---

## CompletionStage in the sample code

```java
public CompletionStage<Result> index() {
    return FutureConverters.toJava(ask(actorSetup.marshallActor, "Report!", 1000))
            .thenApply(response -> ok(response.toString()));
}
```

* Ask the marshall to report (returning a Scala Future)

* Turn the Scala Future into a Java CompletionStage

* when it completes, take its response and turn it into an `OK` response with the string content 


---

## Promises

How do we fill the box? For now, let's use a `Promise`

```scala
val promise = Promise[Int]
val future = promise.future

// later
promise.success(1)
```

"I *promise* at some point in the future I will put an `Int` into this box"


---

## Let's do a network request...

Using the Play WS library, this would return a `Future[WSRequest]`

```scala
  val wsClient = AhcWSClient()
  val f = wsClient
    .url("http://google.com")
    .get()
```

It returns the Future ***immediately***. The future completes ***eventually*** (when the HTTP request succeeds).

---

## Let's do a network request...

```scala
  val wsClient = AhcWSClient()
  val f = wsClient
    .url("https://api.github.com/zen")
    .get()
    
  f.foreach({ req => println(req.body) })
  println("This prints immediately")
```

will print "This prints immediately" before the request for a zen saying from GitHub has returned.


---

## Map 

We have a computation that will complete in the future. Maybe we want to do something with it. We can compose a function onto our future using `map`.

```scala
  val wsClient = AhcWSClient()
  val f = wsClient
    .url("https://api.github.com/zen")
    .map(_.body).map(_.toUpperCase)
    
  f.foreach({ req => println(req.body) })
  println("This prints immediately")    
```

--

*A computation that finishes in the future, with the result then made uppercase, is also a computation that finishes in the future*

---

## FlatMap

* Suppose the next bit of processing is also asynchronous. 

* *Something that finishes in the future, and then doing something else that finishes in the future, produces something that finishes in the future*

* So we should be able to chain two Futures together to get another Future

---

## Let's put our "trite saying" fetcher into a function

```scala
def triteSaying():Future[String] = {
  wsClient
    .url("https://api.github.com/zen")
    .get()
    .map(_.body)
}
```

---

## Let's do two of them

```scala
  triteSaying()
      .andThen({ case x => println(x) })
      .flatMap({ case x => triteSaying()})
      .andThen({ case x => println(x) })

```

---

## Errors

* In synchronous code, we are used to returning exceptions
* When these occur, they propagate up the thread's call stack until they are caught
* But in our concurrent scenario, that's a bit useless -- *we've already moved on*. So instead, failure is a possible state of a `Future`

---

## Error handling

In an event-handling style (returns `Unit`):

```scala
f.onFailure { 
  case NotFoundException(ex) => /* ... */ 
}
```

In a composable computation style (returns a `Future`):

```scala
f.recoverWith { 
  case NotFoundException(ex) => Future.successful(...) 
}
```

---

## Error handling in Java

```java
completionStage.handle((value, exception) -> {
  System.out.println("oops!");
  return null;
});
```