{"action":"created","comment":{"url":"https://api.github.com/repos/akka/akka-http/pulls/comments/96194781","pull_request_review_id":16770141,"id":96194781,"diff_hunk":"@@ -0,0 +1,150 @@\n+/*\n+ * Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>\n+ */\n+package akka.http.javadsl.server;\n+\n+import akka.actor.ActorSystem;\n+import akka.event.Logging;\n+import akka.http.javadsl.ConnectHttp;\n+import akka.http.javadsl.Http;\n+import akka.http.javadsl.ServerBinding;\n+import akka.http.javadsl.settings.ServerSettings;\n+import akka.stream.ActorMaterializer;\n+import scala.runtime.BoxedUnit;\n+\n+import java.io.IOException;\n+import java.util.Optional;\n+import java.util.concurrent.CompletableFuture;\n+import java.util.concurrent.CompletionStage;\n+import java.util.concurrent.ExecutionException;\n+import java.util.concurrent.atomic.AtomicReference;\n+\n+/**\n+ * API MAY CHANGE - EXPERIMENTAL\n+ * Bootstrap trait. It helps booting up an akka-http by only defining the desired routes.\n+ * It offers additional hooks to modify the default behavior\n+ */\n+// @akka.annotation.ApiMayChange // FIXME replace with real annotation once Akka dependency bumped\n+public abstract class HttpApp extends AllDirectives {\n+\n+  private AtomicReference<ServerBinding> serverBinding = new AtomicReference<ServerBinding>();\n+\n+  /**\n+   * Start a server on the specified host and port, using provided settings\n+   * Note that this method is blocking\n+   */\n+  public void startServer(String host, int port, ServerSettings settings) throws ExecutionException, InterruptedException {\n+    startServer(host, port, settings, Optional.empty());\n+  }\n+\n+  /**\n+   * Start a server on the specified host and port, using provided settings and [[ActorSystem]]\n+   * Note that this method is blocking\n+   */\n+  public void startServer(String host, int port, ServerSettings settings, ActorSystem system) throws ExecutionException, InterruptedException {\n+    startServer(host, port, settings, Optional.of(system));\n+  }\n+\n+  /**\n+   * Start a server on the specified host and port, using provided settings and [[ActorSystem]] if present\n+   * Note that this method is blocking\n+   */\n+  public void startServer(String host, int port, ServerSettings settings, Optional<ActorSystem> system) throws ExecutionException, InterruptedException {\n+\n+    final ActorSystem theSystem = system.orElseGet(() -> ActorSystem.create(Logging.simpleName(this).replaceAll(\"\\\\$\", \"\")));\n+    final ActorMaterializer materializer = ActorMaterializer.create(theSystem);\n+\n+    CompletionStage<ServerBinding> bindingFuture = Http\n+      .get(theSystem)\n+      .bindAndHandle(route().flow(theSystem, materializer),\n+        ConnectHttp.toHost(host, port),\n+        settings,\n+        theSystem.log(),\n+        materializer);\n+\n+    bindingFuture.handle((binding, exception) -> {\n+      if (exception != null) {\n+        postHttpBindingFailure(exception);\n+      } else {\n+        //setting the server binding for possible future uses in the client\n+        serverBinding.set(binding);\n+        postHttpBinding(binding);\n+      }\n+      return null;\n+    });\n+\n+    try {\n+      bindingFuture\n+        .thenCompose(ignore -> waitForShutdownSignal(theSystem)) // chaining both futures to fail fast\n+        .toCompletableFuture()\n+        .exceptionally(ignored -> BoxedUnit.UNIT) // If the future fails, we want to complete normally\n+        .get(); // It's waiting forever because maybe there is never a shutdown signal\n+    } finally {\n+      bindingFuture.thenCompose(ServerBinding::unbind).handle( (success, exception) -> {\n+        postServerShutdown(exception, theSystem);\n+        if (!system.isPresent()) {\n+          // we created the system. we should cleanup!\n+          theSystem.terminate();\n+        }\n+        return null;\n+      });\n+    }\n+\n+  }\n+\n+  /**\n+   * It tries to retrieve the {@link ServerBinding} if the server has been successfully started. It throws an {@link IllegalStateException} otherwise.\n+   * You can use this method to attemp to retrieve the {@link ServerBinding} at any point in time to, for example, stop the server due to unexpected circumstances.\n+   */\n+  ServerBinding binding() {\n+    if (serverBinding.get() == null)\n+      throw new IllegalStateException(\"Binding not yet stored. Have you called startServer?\");\n+    return serverBinding.get();\n+  }\n+\n+  /**\n+   * Hook that will be called just after the server termination. Override this method if you want to perform some cleanup actions after the server is stopped\n+   * When problems shutting down {@code possibleFailure} contains the failure occurred. It is null otherwise\n+   */\n+  protected void postServerShutdown(Throwable possibleFailure, ActorSystem system) {\n+    System.out.println(\"Shutting down the server\");\n+  }\n+\n+  /**\n+   * Hook that will be called just after the Http server binding is done. Override this method if you want to perform some actions after the server is up\n+   */\n+  protected void postHttpBinding (ServerBinding binding) {\n+    System.out.println(\"Server online at http://\" + binding.localAddress().getHostName() + \":\" + binding.localAddress().getPort() + \"/\");","path":"akka-http/src/main/java/akka/http/javadsl/server/HttpApp.java","position":117,"original_position":117,"commit_id":"03ae7c17960fda8c37b41b3cd378edf0640735d4","original_commit_id":"03ae7c17960fda8c37b41b3cd378edf0640735d4","user":{"login":"jlprat","id":3337739,"avatar_url":"https://avatars.githubusercontent.com/u/3337739?v=3","gravatar_id":"","url":"https://api.github.com/users/jlprat","html_url":"https://github.com/jlprat","followers_url":"https://api.github.com/users/jlprat/followers","following_url":"https://api.github.com/users/jlprat/following{/other_user}","gists_url":"https://api.github.com/users/jlprat/gists{/gist_id}","starred_url":"https://api.github.com/users/jlprat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jlprat/subscriptions","organizations_url":"https://api.github.com/users/jlprat/orgs","repos_url":"https://api.github.com/users/jlprat/repos","events_url":"https://api.github.com/users/jlprat/events{/privacy}","received_events_url":"https://api.github.com/users/jlprat/received_events","type":"User","site_admin":false},"body":"Following the same structure as `binding`, it could make sense.","created_at":"2017-01-16T10:02:35Z","updated_at":"2017-01-16T10:02:35Z","html_url":"https://github.com/akka/akka-http/pull/542#discussion_r96194781","pull_request_url":"https://api.github.com/repos/akka/akka-http/pulls/542","_links":{"self":{"href":"https://api.github.com/repos/akka/akka-http/pulls/comments/96194781"},"html":{"href":"https://github.com/akka/akka-http/pull/542#discussion_r96194781"},"pull_request":{"href":"https://api.github.com/repos/akka/akka-http/pulls/542"}}},"pull_request":{"url":"https://api.github.com/repos/akka/akka-http/pulls/542","id":94248761,"html_url":"https://github.com/akka/akka-http/pull/542","diff_url":"https://github.com/akka/akka-http/pull/542.diff","patch_url":"https://github.com/akka/akka-http/pull/542.patch","issue_url":"https://api.github.com/repos/akka/akka-http/issues/542","number":542,"state":"open","locked":false,"title":"Provide HttpApp API for Scala and Java","user":{"login":"jlprat","id":3337739,"avatar_url":"https://avatars.githubusercontent.com/u/3337739?v=3","gravatar_id":"","url":"https://api.github.com/users/jlprat","html_url":"https://github.com/jlprat","followers_url":"https://api.github.com/users/jlprat/followers","following_url":"https://api.github.com/users/jlprat/following{/other_user}","gists_url":"https://api.github.com/users/jlprat/gists{/gist_id}","starred_url":"https://api.github.com/users/jlprat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jlprat/subscriptions","organizations_url":"https://api.github.com/users/jlprat/orgs","repos_url":"https://api.github.com/users/jlprat/repos","events_url":"https://api.github.com/users/jlprat/events{/privacy}","received_events_url":"https://api.github.com/users/jlprat/received_events","type":"User","site_admin":false},"body":"Issue: #156\r\nAdd a bootstrap trait that does all the boilerplate for you. Just write as much as you need, not more.\r\n\r\nI converted some of the examples under the docs project to Objects extending `HttpApp` to see how the trait works and how much code it saves.\r\n\r\nFeedback and additional hooks proposal are highly welcomed!","created_at":"2016-11-17T20:56:46Z","updated_at":"2017-01-16T10:02:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"98dfc7c95c92254e0951cca0adb04fe4b87c1dc6","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/akka/akka-http/pulls/542/commits","review_comments_url":"https://api.github.com/repos/akka/akka-http/pulls/542/comments","review_comment_url":"https://api.github.com/repos/akka/akka-http/pulls/comments{/number}","comments_url":"https://api.github.com/repos/akka/akka-http/issues/542/comments","statuses_url":"https://api.github.com/repos/akka/akka-http/statuses/03ae7c17960fda8c37b41b3cd378edf0640735d4","head":{"label":"jlprat:httpApp-bootstrap","ref":"httpApp-bootstrap","sha":"03ae7c17960fda8c37b41b3cd378edf0640735d4","user":{"login":"jlprat","id":3337739,"avatar_url":"https://avatars.githubusercontent.com/u/3337739?v=3","gravatar_id":"","url":"https://api.github.com/users/jlprat","html_url":"https://github.com/jlprat","followers_url":"https://api.github.com/users/jlprat/followers","following_url":"https://api.github.com/users/jlprat/following{/other_user}","gists_url":"https://api.github.com/users/jlprat/gists{/gist_id}","starred_url":"https://api.github.com/users/jlprat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jlprat/subscriptions","organizations_url":"https://api.github.com/users/jlprat/orgs","repos_url":"https://api.github.com/users/jlprat/repos","events_url":"https://api.github.com/users/jlprat/events{/privacy}","received_events_url":"https://api.github.com/users/jlprat/received_events","type":"User","site_admin":false},"repo":{"id":72833610,"name":"akka-http","full_name":"jlprat/akka-http","owner":{"login":"jlprat","id":3337739,"avatar_url":"https://avatars.githubusercontent.com/u/3337739?v=3","gravatar_id":"","url":"https://api.github.com/users/jlprat","html_url":"https://github.com/jlprat","followers_url":"https://api.github.com/users/jlprat/followers","following_url":"https://api.github.com/users/jlprat/following{/other_user}","gists_url":"https://api.github.com/users/jlprat/gists{/gist_id}","starred_url":"https://api.github.com/users/jlprat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jlprat/subscriptions","organizations_url":"https://api.github.com/users/jlprat/orgs","repos_url":"https://api.github.com/users/jlprat/repos","events_url":"https://api.github.com/users/jlprat/events{/privacy}","received_events_url":"https://api.github.com/users/jlprat/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jlprat/akka-http","description":"The Streaming-first HTTP server/module of Akka","fork":true,"url":"https://api.github.com/repos/jlprat/akka-http","forks_url":"https://api.github.com/repos/jlprat/akka-http/forks","keys_url":"https://api.github.com/repos/jlprat/akka-http/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jlprat/akka-http/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jlprat/akka-http/teams","hooks_url":"https://api.github.com/repos/jlprat/akka-http/hooks","issue_events_url":"https://api.github.com/repos/jlprat/akka-http/issues/events{/number}","events_url":"https://api.github.com/repos/jlprat/akka-http/events","assignees_url":"https://api.github.com/repos/jlprat/akka-http/assignees{/user}","branches_url":"https://api.github.com/repos/jlprat/akka-http/branches{/branch}","tags_url":"https://api.github.com/repos/jlprat/akka-http/tags","blobs_url":"https://api.github.com/repos/jlprat/akka-http/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jlprat/akka-http/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jlprat/akka-http/git/refs{/sha}","trees_url":"https://api.github.com/repos/jlprat/akka-http/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jlprat/akka-http/statuses/{sha}","languages_url":"https://api.github.com/repos/jlprat/akka-http/languages","stargazers_url":"https://api.github.com/repos/jlprat/akka-http/stargazers","contributors_url":"https://api.github.com/repos/jlprat/akka-http/contributors","subscribers_url":"https://api.github.com/repos/jlprat/akka-http/subscribers","subscription_url":"https://api.github.com/repos/jlprat/akka-http/subscription","commits_url":"https://api.github.com/repos/jlprat/akka-http/commits{/sha}","git_commits_url":"https://api.github.com/repos/jlprat/akka-http/git/commits{/sha}","comments_url":"https://api.github.com/repos/jlprat/akka-http/comments{/number}","issue_comment_url":"https://api.github.com/repos/jlprat/akka-http/issues/comments{/number}","contents_url":"https://api.github.com/repos/jlprat/akka-http/contents/{+path}","compare_url":"https://api.github.com/repos/jlprat/akka-http/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jlprat/akka-http/merges","archive_url":"https://api.github.com/repos/jlprat/akka-http/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jlprat/akka-http/downloads","issues_url":"https://api.github.com/repos/jlprat/akka-http/issues{/number}","pulls_url":"https://api.github.com/repos/jlprat/akka-http/pulls{/number}","milestones_url":"https://api.github.com/repos/jlprat/akka-http/milestones{/number}","notifications_url":"https://api.github.com/repos/jlprat/akka-http/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jlprat/akka-http/labels{/name}","releases_url":"https://api.github.com/repos/jlprat/akka-http/releases{/id}","deployments_url":"https://api.github.com/repos/jlprat/akka-http/deployments","created_at":"2016-11-04T09:34:08Z","updated_at":"2016-11-04T09:34:10Z","pushed_at":"2017-01-16T09:03:13Z","git_url":"git://github.com/jlprat/akka-http.git","ssh_url":"git@github.com:jlprat/akka-http.git","clone_url":"https://github.com/jlprat/akka-http.git","svn_url":"https://github.com/jlprat/akka-http","homepage":"http://akka.io","size":8654,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"akka:master","ref":"master","sha":"8ef680fb109e4dde6d7dcb2dc4d2a42521d22cf9","user":{"login":"akka","id":1496237,"avatar_url":"https://avatars.githubusercontent.com/u/1496237?v=3","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"repo":{"id":66077955,"name":"akka-http","full_name":"akka/akka-http","owner":{"login":"akka","id":1496237,"avatar_url":"https://avatars.githubusercontent.com/u/1496237?v=3","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/akka/akka-http","description":"The Streaming-first HTTP server/module of Akka","fork":false,"url":"https://api.github.com/repos/akka/akka-http","forks_url":"https://api.github.com/repos/akka/akka-http/forks","keys_url":"https://api.github.com/repos/akka/akka-http/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akka/akka-http/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akka/akka-http/teams","hooks_url":"https://api.github.com/repos/akka/akka-http/hooks","issue_events_url":"https://api.github.com/repos/akka/akka-http/issues/events{/number}","events_url":"https://api.github.com/repos/akka/akka-http/events","assignees_url":"https://api.github.com/repos/akka/akka-http/assignees{/user}","branches_url":"https://api.github.com/repos/akka/akka-http/branches{/branch}","tags_url":"https://api.github.com/repos/akka/akka-http/tags","blobs_url":"https://api.github.com/repos/akka/akka-http/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akka/akka-http/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akka/akka-http/git/refs{/sha}","trees_url":"https://api.github.com/repos/akka/akka-http/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akka/akka-http/statuses/{sha}","languages_url":"https://api.github.com/repos/akka/akka-http/languages","stargazers_url":"https://api.github.com/repos/akka/akka-http/stargazers","contributors_url":"https://api.github.com/repos/akka/akka-http/contributors","subscribers_url":"https://api.github.com/repos/akka/akka-http/subscribers","subscription_url":"https://api.github.com/repos/akka/akka-http/subscription","commits_url":"https://api.github.com/repos/akka/akka-http/commits{/sha}","git_commits_url":"https://api.github.com/repos/akka/akka-http/git/commits{/sha}","comments_url":"https://api.github.com/repos/akka/akka-http/comments{/number}","issue_comment_url":"https://api.github.com/repos/akka/akka-http/issues/comments{/number}","contents_url":"https://api.github.com/repos/akka/akka-http/contents/{+path}","compare_url":"https://api.github.com/repos/akka/akka-http/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akka/akka-http/merges","archive_url":"https://api.github.com/repos/akka/akka-http/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akka/akka-http/downloads","issues_url":"https://api.github.com/repos/akka/akka-http/issues{/number}","pulls_url":"https://api.github.com/repos/akka/akka-http/pulls{/number}","milestones_url":"https://api.github.com/repos/akka/akka-http/milestones{/number}","notifications_url":"https://api.github.com/repos/akka/akka-http/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akka/akka-http/labels{/name}","releases_url":"https://api.github.com/repos/akka/akka-http/releases{/id}","deployments_url":"https://api.github.com/repos/akka/akka-http/deployments","created_at":"2016-08-19T11:33:36Z","updated_at":"2017-01-15T12:32:40Z","pushed_at":"2017-01-16T09:03:15Z","git_url":"git://github.com/akka/akka-http.git","ssh_url":"git@github.com:akka/akka-http.git","clone_url":"https://github.com/akka/akka-http.git","svn_url":"https://github.com/akka/akka-http","homepage":"http://akka.io","size":8615,"stargazers_count":202,"watchers_count":202,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":76,"mirror_url":null,"open_issues_count":341,"forks":76,"open_issues":341,"watchers":202,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/akka/akka-http/pulls/542"},"html":{"href":"https://github.com/akka/akka-http/pull/542"},"issue":{"href":"https://api.github.com/repos/akka/akka-http/issues/542"},"comments":{"href":"https://api.github.com/repos/akka/akka-http/issues/542/comments"},"review_comments":{"href":"https://api.github.com/repos/akka/akka-http/pulls/542/comments"},"review_comment":{"href":"https://api.github.com/repos/akka/akka-http/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/akka/akka-http/pulls/542/commits"},"statuses":{"href":"https://api.github.com/repos/akka/akka-http/statuses/03ae7c17960fda8c37b41b3cd378edf0640735d4"}}}}
{"actor":{"display_login":"jlprat"}}