/** * <p>Render this response using the renderer's own threads and return a future indicating whether the rendering * was successful. The data list tree will be traversed asynchronously, and * the pertinent methods will be called as data becomes available.</p> * * <p>If rendering fails, the exception causing this will be wrapped in an * ExecutionException and thrown from blocked calls to Future.get()</p> * * @return a future indicating whether rendering was successful */ @Override public final ListenableFuture<Boolean> render(OutputStream stream, RESPONSE response, Execution execution, Request request) { if (beforeHandoverMode) { // rendering has already started or is already complete beforeHandoverMode = false; if ( ! dataListListenerStack.isEmpty() && dataListListenerStack.getFirst().list.incoming().isComplete()) { // We're not waiting for async completion, so kick off more rendering due to the implicit complete // (return Response from chain) causing this method to be called getExecutor().execute(dataListListenerStack.getFirst()); } return success; } else { // This is the start of rendering return startRender(stream, response, execution, request); } }
private ListenableFuture<Boolean> startRender(OutputStream stream, RESPONSE response, Execution execution, Request request) { this.response = response; this.stream = stream; this.execution = execution; DataListListener parentOfTopLevelListener = new DataListListener(new ParentOfTopLevel(request,response.data()), null); dataListListenerStack.addFirst(parentOfTopLevelListener); success = SettableFuture.create(); try { getExecutor().execute(parentOfTopLevelListener); } catch (RejectedExecutionException e) { parentOfTopLevelListener.closeIO(e); } return success; }