This is an automated email from the ASF dual-hosted git repository.

fanningpj pushed a commit to branch wip-adding-tests
in repository 
https://gitbox.apache.org/repos/asf/incubator-pekko-http-quickstart-scala-g8.git

commit 1d766ec6d689477aae1f00582b4f6e6225df1ac0
Author: henrikengstrom <[email protected]>
AuthorDate: Wed Jul 19 15:48:37 2017 -0400

    Further fixes based on feedback.
---
 docs/src/main/paradox/backend.md                   |  6 +-
 docs/src/main/paradox/index.md                     | 30 ++++++--
 docs/src/main/paradox/intellij-idea.md             |  4 +-
 docs/src/main/paradox/running-the-application.md   | 22 ++++--
 docs/src/main/paradox/server-class.md              | 89 +++++++++++-----------
 src/main/g8/build.sbt                              |  8 +-
 .../lightbend/akka/http/sample/JsonSupport.scala   |  3 +-
 .../akka/http/sample/QuickstartServer.scala        | 73 ++++++++++--------
 .../akka/http/sample/UserRegistryActor.scala       | 16 ++--
 9 files changed, 149 insertions(+), 102 deletions(-)

diff --git a/docs/src/main/paradox/backend.md b/docs/src/main/paradox/backend.md
index 8de403b..788a694 100644
--- a/docs/src/main/paradox/backend.md
+++ b/docs/src/main/paradox/backend.md
@@ -1,9 +1,11 @@
 Backend
 -------
 
-It is probably an exaggeration to call this for a "backend" since it, in this 
sample, only consists of a basic actor. In a real system, we would have many 
actors interacting with each other and perhaps a database or microservices. 
However, since the focus of this tutorial is on Akka HTTP, it is not very 
important what this backend does but more how to interact with a backend from 
within Akka HTTP. Hopefully, you already have a good grasp of how to 
communicate back and forth between Akka  [...]
+It is probably an exaggeration to call this for a "backend" since it, in this 
sample, only consists of a basic actor. In a real system, we would have many 
actors interacting with each other and perhaps a database or microservices. 
Also, we suggest designing the backend first and thereafter expose its 
functionality via an HTTP server.
 
-If you feel you should brush up your Akka Actor knowledge, then the [getting 
started guide]((http://developer.lightbend.com/guides/akka-quickstart-scala/)) 
for Akka actors tutorial is a good start.
+However, since the focus of this tutorial is on Akka HTTP, it is not very 
important what this backend does but more how to interact with a backend from 
within Akka HTTP. Hopefully, you already have a good grasp of how to 
communicate back and forth between Akka HTTP and actors by now.
+
+If you feel you should brush up your Akka Actor knowledge, then the 
[Quickstart 
guide]((http://developer.lightbend.com/guides/akka-quickstart-scala/)) for Akka 
actors tutorial is a good start.
 
 The sample code in the `UserRegistryActor` is very simple. It keeps registered 
users in a `Set`. Once it receives messages it will match those into what 
action it should take:
 
diff --git a/docs/src/main/paradox/index.md b/docs/src/main/paradox/index.md
index 72b554a..a1408a5 100644
--- a/docs/src/main/paradox/index.md
+++ b/docs/src/main/paradox/index.md
@@ -9,7 +9,7 @@ This Hello World example demonstrates some Akka HTTP 
fundamentals. Within 30 min
 
 ## Prerequisite
 
-Having a basic understanding of Akka actors will help the reader of this 
guide. There is a [getting started 
guide](https://developer.lightbend.com/guides/akka-quickstart-scala/) for Akka 
actors should you feel like brushing up your knowledge thereof.
+Having a basic understanding of Akka actors will help the reader of this 
guide. There is a [Quickstart 
guide](https://developer.lightbend.com/guides/akka-quickstart-scala/) for Akka 
actors should you feel like brushing up your knowledge thereof.
 
 ## Downloading the example
 
@@ -35,7 +35,7 @@ To run Hello World:
 
 In a console, change directories to the top level of the unzipped project.
 
-For example, if you used the default project name, 
`akka-http-quickstart-scala`, and extracted the project to your root directory, 
from the root directory, enter: cd akka-http-quickstart-scala
+For example, if you used the default project name, 
`akka-http-quickstart-scala`, and extracted the project to your root directory, 
from the root directory, enter:
 
 Enter `./sbt` on OSX/Linux or run `sbt.bat` on Windows to start 
[sbt](http://www.scala-sbt.org).
 
@@ -43,6 +43,20 @@ sbt downloads project dependencies. The `>` prompt indicates 
sbt has started in
 
 At the sbt prompt, enter `run`.
 
+OSX/Linux
+: ```
+$ cd akka-http-quickstart-scala
+$ ./sbt
+> run
+```
+
+Windows
+: ```
+$ cd akka-http-quickstart-scala
+$ sbt.bat
+> run
+```
+
 sbt builds the project and runs Hello World.
 
 The output should look something like this:
@@ -61,24 +75,24 @@ Congratulations, you just ran your first Akka HTTP app. Now 
take a look at what
 
 ## What Hello World does
 
-When Hello World starts up it creates an ActorSystem and registers so-called 
routes that are available in this ActorSystem. The routes are bound to a port, 
in this case, `localhost:8080`. Below is an overview of what things look like 
when the application starts:
+In this example, a simple user registry service represented by an actor is 
presented to consumers as a [REST 
service](https://en.wikipedia.org/wiki/Representational_state_transfer).
 
-![Architecture](images/hello-akka-http.png)
+When Hello World starts up, it creates an ActorSystem and an instance of the 
`UserRegistryActor` that implements the functionality of the service. Then the 
HTTP service is started by binding so-called "routes" to the given interface 
and port, in this case, `localhost:8080`. Below is an overview of what things 
look like after the application has started:
 
-In this sample application, we are implementing a [REST 
service](https://en.wikipedia.org/wiki/Representational_state_transfer). The 
idea is to build a simple user registry service.
+![Architecture](images/hello-akka-http.png)
 
-The endpoints available are `/users` and `/user` with some attached HTTP 
directives and parameters/payloads. When invoked, endpoints will interact with 
an actor, "userRegistryActor", which represents the business logic of this 
sample application.
+The value `routes` defines the endpoint `/users` that route requests to the 
business logic actor. Routes are defined in terms of so-called "directives" 
which are basic building blocks of Akka Http that define how requests and 
responses are handled and how data is translated from HTTP to and from your 
domain objects.
 
 In the following sections, we will take a detailed look at the individual 
pieces of this application.
 
 ## The Akka HTTP philosophy
 
-Akka HTTP is designed specifically as "not-a-framework," not because we don’t 
like frameworks, but for use cases where a framework is not the right choice.  
Akka HTTP is for building integration layers based on HTTP and as such tries to 
"stay on the sidelines."  Therefore, a typical application doesn't sit on top 
of Akka HTTP but instead on top of whatever makes sense and uses Akka HTTP 
merely for the HTTP integration needs.
+Akka HTTP is designed specifically as "not-a-framework," not because we don’t 
like frameworks, but for use cases where a framework is not the right choice.  
Akka HTTP is for building integration layers based on HTTP and as such tries to 
"stay on the sidelines."  Therefore, a typical application doesn't sit on top 
of Akka HTTP but instead on top of whatever makes sense and uses Akka HTTP 
merely for the HTTP integration needs. Should you look for a web framework it 
is recommended to take a [...]
 
 @@@index
 
-* [The server](server-class.md)
 * [The backend](backend.md)
+* [The server](server-class.md)
 * [JSON](json.md)
 * [Running the application](running-the-application.md)
 * [IntelliJ IDEA](intellij-idea.md)
diff --git a/docs/src/main/paradox/intellij-idea.md 
b/docs/src/main/paradox/intellij-idea.md
index f55a8ad..9dd3629 100644
--- a/docs/src/main/paradox/intellij-idea.md
+++ b/docs/src/main/paradox/intellij-idea.md
@@ -9,11 +9,11 @@ Open IntelliJ and select File -> Open... and point to the 
directory where you ha
 
 ![Open Project](images/idea-open-project.png)
 
-Fill out the settings according to the above and press `OK` to import the 
project. If IntelliJ will warn about missing Scala SDK, it is only to follow 
the instructions to add support.
+Fill out the settings according to the above and press `OK` to import the 
project. If IntelliJ will warn about missing Scala SDK, just follow the 
instructions to add support.
 
 ## Inspecting the code
 
-If we open up the file 
`src/main/scala/com/lightbend/akka/http/sample/QuickstartServer.scala` we can 
see a lot of lines beginning with //# .... These lines are used as directives 
for this documentation. To get rid of these lines from the source code we can 
utilize the awesome Find/Replace functionality in IntelliJ. Select Edit -> Find 
-> Replace in Path.... Check the Regex box and add the following regex [//#].* 
and click on Replace in Find Window.... Select to replace all occurrences an 
[...]
+If we open up the file 
`src/main/scala/com/lightbend/akka/http/sample/QuickstartServer.scala` we can 
see a lot of lines beginning with //# .... These lines are used as directives 
for this documentation. To get rid of these lines from the source code we can 
utilize the awesome Find/Replace functionality in IntelliJ. Select Edit -> Find 
-> Replace in Path.... Check the Regex box and add the following regex 
`[//#].*` and click on Replace in Find Window.... Select to replace all 
occurrences  [...]
 
 ## Running the application
 
diff --git a/docs/src/main/paradox/running-the-application.md 
b/docs/src/main/paradox/running-the-application.md
index ac9d6d1..3142b52 100644
--- a/docs/src/main/paradox/running-the-application.md
+++ b/docs/src/main/paradox/running-the-application.md
@@ -11,13 +11,21 @@ sbt uses a build.sbt file to handle the project. This 
project’s build.sbt file
 
 ## Running the project
 
-We run the application from a console/terminal window:
+We run the application from a console/terminal window and enter the following 
commands:
 
-1. Enter `./sbt` on OSX/Linux or `sbt.bat` on Windows
-
-sbt downloads project dependencies. The `>` prompt indicates sbt has started 
in interactive mode.
+OSX/Linux
+: ```
+$ cd akka-http-quickstart-scala
+$ ./sbt
+> run
+```
 
-2. At the sbt prompt, enter `run`.
+Windows
+: ```
+$ cd akka-http-quickstart-scala
+$ sbt.bat
+> run
+```
 
 The output should look like this:
 
@@ -28,9 +36,9 @@ Server online at http://localhost:8080/
 Press RETURN to stop...
 ```
 
-## Testing the application
+## Interacting with the application
 
-The Akka HTTP server is now running, and we will use the 
[cURL](https://en.wikipedia.org/wiki/CURL) command to test the application. If 
you  prefer to use your browser to test the service then a tool like 
[RESTClient](http://restclient.net/) may be good to install.
+The Akka HTTP server is now running, and we will use the 
[cURL](https://en.wikipedia.org/wiki/CURL) command to test the application. If 
you prefer to use your browser to test the service then a tool like 
[RESTClient](http://restclient.net/) may be good to install.
 
 Open another console/terminal window to investigate the functionality of the 
application.
 
diff --git a/docs/src/main/paradox/server-class.md 
b/docs/src/main/paradox/server-class.md
index c10f9ad..daefde2 100644
--- a/docs/src/main/paradox/server-class.md
+++ b/docs/src/main/paradox/server-class.md
@@ -1,79 +1,80 @@
-The main class
-----------------
+The Akka HTTP server class
+--------------------------
 
-Let's dissect the main class, `QuickstartServer`. We make this class runnable 
by extending `App` (we will discuss the trait `JsonSupport` later):
+Let's dissect the server class, `QuickstartServer`. We make this class 
runnable by extending `App` (we will discuss the trait `JsonSupport` later):
 
 @@snip 
[QuickstartServer.scala]($g8src$/scala/com/lightbend/akka/http/sample/QuickstartServer.scala)
 { #main-class }
 
-Now that we have a class to run we should add some Akka HTTP fundamentals with 
which we will build our RESTful web service:
-
-* define routes bound to endpoints and HTTP directives
-* create a server bound to an IP and port that will handle all requests
-* add error handling for when something goes wrong
-
-Let us take a look at each of these steps here below.
+Now that we have a class to run we should add some Akka HTTP fundamentals with 
which we will build our RESTful web service. The aim is to use routes to define 
endpoints by choosing what to do for which requests.
 
 ## Routes
 
 For our service we want to define the following endpoints:
 
-| Path        | Http directive  | Intent             | Returns              |
+| Path        | Http method     | Intent             | Returns              |
 |-------------|-----------------|--------------------|----------------------|
-| /user       | POST            | Create a new user  | Confirmation message |
-| /user/$ID   | GET             | Retrieve a user    | JSON payload         |
-| /user/$ID   | DELETE          | Remove a user      | Confirmation message |
+| /users      | POST            | Create a new user  | Confirmation message |
 | /users      | GET             | Retrieve all users | JSON payload         |
+| /users/$ID  | GET             | Retrieve a user    | JSON payload         |
+| /users/$ID  | DELETE          | Remove a user      | Confirmation message |
 
-Akka HTTP provides a [domain-specific 
language](https://en.wikipedia.org/wiki/Domain-specific_language) (DSL) to 
simplify the routes/endpoints definition. Each route is composed of one or more 
`akka.http.scaladsl.server.Directives`, e.g. `path`, `get`, `post`, `complete`, 
etc.
+Akka HTTP provides a [domain-specific 
language](https://en.wikipedia.org/wiki/Domain-specific_language) (DSL) to 
simplify the routes/endpoints definition. Each route is composed of one or more 
`akka.http.scaladsl.server.Directives`, e.g. `path`, `get`, `post`, `complete`, 
etc. There is also a [low-level 
API](http://doc.akka.io/docs/akka-http/current/scala/http/low-level-server-side-api.html)
 that allows to inspect requests and create responses manually.
 
-### Creating a new user
+### Creating and retrieving a user
 
-Let us take a look at the source code for the first endpoint, the `/user` URI 
with a `POST` directive, used to create a new user:
+Let us take a look at the source code for the first two endpoints, the 
`/users` path with `GET` and `POST` HTTP methods:
 
-@@snip 
[QuickstartServer.scala]($g8src$/scala/com/lightbend/akka/http/sample/QuickstartServer.scala)
 { #user-post }
+@@snip 
[QuickstartServer.scala]($g8src$/scala/com/lightbend/akka/http/sample/QuickstartServer.scala)
 { #users-get-post }
 
-The snippet above contains a couple of interesting building blocks:
+The snippet above contains a couple of interesting Akka HTTP building blocks:
 
-* `path` : matches against the incoming URI, in this case, we want to get all 
requests that matches `user`.
-* `post` : matches against the incoming Http directive, in this case, we are 
matching against `POST`.
-* `entity(as[User])` : automatically converts the incoming payload, in this 
case, we expect JSON, into an entity. We will look more at this functionality 
in the @ref:[JSON](json.md) section.
-* `complete` : used to reply back to the request. The `StatusCodes.Created` is 
translated to Http response code 201. We also send back information to the 
caller in the form of a string.    
+**Generic functionality**
 
-When this `Route` is called, we want to create a new user, and we do so by 
sending a message to the actor `userRegistryActor`. We will look at the 
implementation of this actor later.
+* `pathPrefix("users")` : the path that is used to match the incoming request 
against.
+* `pathEnd` : used on an inner-level to discriminate “path already fully 
matched” from other alternatives. Will, in this case, match on the "users" path.
+* `~`: concatenates two or more route alternatives. Routes are attempted one 
after another. If a route rejects a request, the next route in the chain is 
attempted. This continues until a route in the chain produces a response. If 
all route alternatives reject the request, the concatenated route rejects the 
route as well. In that case, route alternatives on the next higher level are 
attempted. If the root level route rejects the request as well, then an error 
response is returned that con [...]
 
-### Retrieving and removing a user
+**Retrieving users**
 
-Next we need to define how to retrieve and remove a user, i.e. for the case 
when the URI `/user/$ID` is used where `$ID` is the id of the user:
+* `get` : matches against `GET` HTTP method.
+* `complete` : completes a request which means creating and returning a 
response from the arguments.
 
-@@snip 
[QuickstartServer.scala]($g8src$/scala/com/lightbend/akka/http/sample/QuickstartServer.scala)
 { #user-get-delete }
+**Creating a user**
 
-This Route snippet contains a couple of interesting concepts:
+* `post` : matches against `POST` HTTP method.
+* `entity(as[User])` : converts the HTTP request body into a domain object of 
type User. Implicitly, we assume that the request contains application/json 
content. We will look at how this works in the @ref:[JSON](json.md) section.
+* `complete` : completes a request which means creating and returning a 
response from the arguments. Note, how the tuple (StatusCodes.Created, "...") 
of type (StatusCode, String) is implicitly converted to a response with the 
given status code and a text/plain body with the given string.
 
-* `path("user" / Segment) { => user` : this bit of code matches against URIs 
of the exact format `/user/$ID` and the `Segment` is automatically extracted 
into the `user` variable so that we can get to the value passed in the URI. For 
example `/user/Bruce` will populate the `user` variable with the value "Bruce."
-* `get` : matches against the incoming Http directive.
+### Retrieving and removing a user
 
-Let's break down the "business logic" in the first Route:
+Next we need to define how to retrieve and remove a user, i.e. for the case 
when the URI `/users/$ID` is used where `$ID` is the id of the user:
 
-@@snip 
[QuickstartServer.scala]($g8src$/scala/com/lightbend/akka/http/sample/QuickstartServer.scala)
 { #retrieve-user-info }
+@@snip 
[QuickstartServer.scala]($g8src$/scala/com/lightbend/akka/http/sample/QuickstartServer.scala)
 { #users-get-delete }
 
-The code above uses the so-called 
[ask](http://doc.akka.io/docs/akka/current/scala/actors.html#send-messages) in 
Akka. This will send a message asynchronously and return a `Future` 
representing a _possible_ reply. The code above maps the reply to the type 
`UserInfo`. When the future completes, it will use the second part of the code 
to evaluate to either `Success`, with or without a result, or a `Failure`. 
Regardless of the outcome of the future, we should return something to the 
request [...]
+This Route snippet contains a couple of interesting concepts:
 
-The remaining directives used for this route are:
+**Generic functionality**
 
-* `~` : fuses `Route`s together - this will become more apparent when you see 
the complete `Route` definition here below.
-* `delete` : matches against the Http directive `DELETE`.
+* `pathPrefix("users")` : the path that is used to match the incoming request 
against.
+* `path(Segment) { => user` : this bit of code matches against URIs of the 
exact format `/users/$ID` and the `Segment` is automatically extracted into the 
`user` variable so that we can get to the value passed in the URI. For example 
`/users/Bruce` will populate the `user` variable with the value "Bruce." There 
is plenty of more features available for handling of URIs, see [pattern 
matchers](http://doc.akka.io/docs/akka-http/current/scala/http/routing-dsl/path-matchers.html#basic-pathmat
 [...]
+* `~`: concatenates two or more route alternatives. Routes are attempted one 
after another. If a route rejects a request, the next route in the chain is 
attempted. This continues until a route in the chain produces a response. If 
all route alternatives reject the request, the concatenated route rejects the 
route as well. In that case, route alternatives on the next higher level are 
attempted. If the root level route rejects the request as well, then an error 
response is returned that con [...]
+
+**Retrieving a user**
 
-The "business logic" for when deleting a user is straight forward; send an 
instruction about removing a user to the user registry actor and return a 
status code to the client (which in this case is `StatusCodes.OK`, i.e. Http 
status code 200)
+* `get` : matches against `GET` HTTP method.
+* `complete` : completes a request which means creating and returning a 
response from the arguments.
 
-### Retrieving all users
+Let's break down the "business logic":
 
-Finally we should implement functionality to retrieve all registered users:
+@@snip 
[QuickstartServer.scala]($g8src$/scala/com/lightbend/akka/http/sample/QuickstartServer.scala)
 { #retrieve-user-info }
+
+The `rejectEmptyResponse` here above is a convenience method that 
automatically unwraps a future, handles an `Option` by converting `Some` into a 
successful response, returns a HTTP status code 404 for `None`, and passes on 
to the `ExceptionHandler` in case of an error, which returns the HTTP status 
code 500 by default.
 
-@@snip 
[QuickstartServer.scala]($g8src$/scala/com/lightbend/akka/http/sample/QuickstartServer.scala)
 { #users-get }
+**Deleting a user**
 
-This code is based on the same structure as the code above, send a message to 
the user registry actor using an `ask` and pass on the `Future` to the 
`complete` method.
+* `delete` : matches against the Http directive `DELETE`.
 
-Why do we not use an `onComplete` as we did for when retrieving a particular 
user? The difference is that when we use `GetUsers` there will always be 
something returned; an empty list means that there are no registered users. 
However, when we asked for a particular user ID, there might be the case that 
there is no such user recorded and we need a way to tell this to the client. 
When sent a `GetUser(name)` the user registry actor therefore send back an 
`Option[UserInfo]`. It could be that [...]
+The "business logic" for when deleting a user is straight forward; send an 
instruction about removing a user to the user registry actor, wait for the 
response and return an appropriate HTTP status code to the client.
 
 ### The complete Route
 
@@ -92,7 +93,7 @@ To set up an Akka HTTP server we must first define some 
implicit values that wil
 What does the above mean and why do we need it?
 
 * `ActorSystem` : the context in which actors will run. What actors, you may 
wonder? Akka Streams uses actors under the hood, and the actor system defined 
in this `val` will be picked up and used by Streams.
-* `ActorMaterializer` : also Akka Streams related - it uses the materializer 
to allocate all the necessary resources it needs to run.
+* `ActorMaterializer` : while the ActorSystem is the host of all thread pools 
and live actors, an ActorMaterializer is specific to Akka Streams and is what 
makes them run. The ActorMaterializer interprets stream descriptions into 
executable entities which are run on actors, and this is why it requires an 
ActorSystem to function.
 
 With that defined we can move on to instantiate the server:
 
@@ -104,7 +105,7 @@ We should also add code for stopping the server. To do so 
we use the `StdIn.read
 
 ## Error handling
 
-Finally, we should take a look at how to handle errors. We know, as the astute 
engineers we are, that errors will happen. We should prepare our program for 
this and error handling should not be an afterthought when we build systems.
+Finally, we should take a look at how to [handle 
errors](http://doc.akka.io/docs/akka-http/current/scala/http/routing-dsl/exception-handling.html).
 We know, as the astute engineers we are, that errors will happen. We should 
prepare our program for this and error handling should not be an afterthought 
when we build systems.
 
 In this sample, we use a very simple exception handler which catches all 
unexpected exceptions and responds back to the client with an 
`InternalServerError` (HTTP status code 500) with an error message and for what 
URI the exception happened. We extract the URI by using the `extractUri` 
directive.
 
diff --git a/src/main/g8/build.sbt b/src/main/g8/build.sbt
index 030ddd5..c286488 100644
--- a/src/main/g8/build.sbt
+++ b/src/main/g8/build.sbt
@@ -7,10 +7,14 @@ lazy val root = (project in file(".")).
       organization    := "com.example",
       scalaVersion    := "2.12.2"
     )),
-    name := "$name$",
+    name := "Akka Http Quickstart",
     libraryDependencies ++= Seq(
       "com.typesafe.akka" %% "akka-http"            % akkaHttpVersion,
       "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
-      "com.typesafe.akka" %% "akka-stream"          % akkaVersion
+      "com.typesafe.akka" %% "akka-stream"          % akkaVersion,
+      "com.typesafe.akka" %% "akka-http-xml"     % akkaHttpVersion,
+      "com.typesafe.akka" %% "akka-stream"       % akkaVersion,
+      "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test,
+      "org.scalatest"     %% "scalatest"         % "3.0.1"         % Test
     )
   )
diff --git 
a/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/JsonSupport.scala 
b/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/JsonSupport.scala
index 6f19b73..ffebd52 100644
--- 
a/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/JsonSupport.scala
+++ 
b/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/JsonSupport.scala
@@ -3,7 +3,8 @@ package com.lightbend.akka.http.sample
 import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
 import spray.json.DefaultJsonProtocol
 
-trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
+trait JsonSupport extends SprayJsonSupport {
+  import DefaultJsonProtocol._
   implicit val userJsonFormat = jsonFormat3(User)
   implicit val usersJsonFormat = jsonFormat1(Users)
 }
diff --git 
a/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/QuickstartServer.scala
 
b/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/QuickstartServer.scala
index 1279967..3181755 100644
--- 
a/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/QuickstartServer.scala
+++ 
b/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/QuickstartServer.scala
@@ -35,6 +35,8 @@ object QuickstartServer extends App with JsonSupport {
   implicit val executionContext: ExecutionContext = system.dispatcher
 
   val userRegistryActor: ActorRef = system.actorOf(UserRegistryActor.props, 
"userRegistryActor")
+
+  // Required by the `ask` (?) method below
   implicit val timeout = Timeout(5 seconds)
 
   //#exception-handler
@@ -48,41 +50,50 @@ object QuickstartServer extends App with JsonSupport {
 
   //#all-routes
   lazy val routes: Route =
-    //#user-post
-    path("user") {
-      post {
-        entity(as[User]) { user =>
-          userRegistryActor ! CreateUser(user)
-          complete((StatusCodes.Created, s"User ${user.name} created."))
-        }
-      }
-    } ~ //#user-post
-      //#user-get-delete
-      path("user" / Segment) { name =>
-        get {
-          //#retrieve-user-info
-          val userInfo: Future[UserInfo] = (userRegistryActor ? 
GetUser(name)).mapTo[UserInfo]
-          onComplete(userInfo) { r =>
-            r match {
-              case Success(UserInfo(Some(user))) => complete(user)
-              case Success(UserInfo(None)) => complete((StatusCodes.OK, s"User 
$name is not registered."))
-              case Failure(ex) => complete((StatusCodes.InternalServerError, 
ex))
-            }
-          }
-          //#retrieve-user-info
-        } ~
-          delete {
-            userRegistryActor ! DeleteUser(name)
-            complete((StatusCodes.OK, s"User $name deleted."))
-          }
-      } ~ //#user-get-delete
-      //#users-get
-      path("users") {
+    //#users-get-post
+    //#users-get-delete
+    pathPrefix("users") {
+      //#users-get-delete
+      pathEnd {
         get {
           val users: Future[Users] = (userRegistryActor ? 
GetUsers).mapTo[Users]
           complete(users)
+        } ~
+          post {
+            entity(as[User]) { user =>
+              val userCreated: Future[ActionPerformed] = (userRegistryActor ? 
CreateUser(user)).mapTo[ActionPerformed]
+              onComplete(userCreated) { r =>
+                r match {
+                  case Success(ActionPerformed(description)) => 
complete((StatusCodes.Created, description))
+                  case Failure(ex) => 
complete((StatusCodes.InternalServerError, ex))
+                }
+              }
+            }
+          }
+      } ~
+        //#users-get-post
+        //#users-get-delete
+        path(Segment) { name =>
+          get {
+            //#retrieve-user-info
+            val maybeUser: Future[Option[User]] = (userRegistryActor ? 
GetUser(name)).mapTo[Option[User]]
+            rejectEmptyResponse {
+              complete(maybeUser)
+            }
+            //#retrieve-user-info
+          } ~
+            delete {
+              val userDeleted: Future[ActionPerformed] = (userRegistryActor ? 
DeleteUser(name)).mapTo[ActionPerformed]
+              onComplete(userDeleted) { r =>
+                r match {
+                  case Success(ActionPerformed(description)) => 
complete((StatusCodes.OK, description))
+                  case Failure(ex) => 
complete((StatusCodes.InternalServerError, ex))
+                }
+              }
+            }
         }
-      } //#users-get
+      //#users-get-delete
+    }
   //#all-routes
 
   //#http-server
diff --git 
a/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/UserRegistryActor.scala
 
b/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/UserRegistryActor.scala
index 718f63e..7a910ac 100644
--- 
a/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/UserRegistryActor.scala
+++ 
b/src/main/g8/src/main/scala/com/lightbend/akka/http/sample/UserRegistryActor.scala
@@ -3,13 +3,13 @@ package com.lightbend.akka.http.sample
 import akka.actor.{ Actor, ActorLogging, Props }
 import scala.collection.mutable.Set
 
-case class UserInfo(maybeUser: Option[User])
 //#user-case-classes
 case class User(name: String, age: Int, countryOfResidence: String)
 case class Users(users: Seq[User])
 //#user-case-classes
 
 object UserRegistryActor {
+  final case class ActionPerformed(description: String)
   final case object GetUsers
   final case class CreateUser(user: User)
   final case class GetUser(name: String)
@@ -24,9 +24,15 @@ class UserRegistryActor extends Actor with ActorLogging {
   val users: Set[User] = Set.empty[User]
 
   def receive = {
-    case GetUsers => sender ! Users(users.toSeq)
-    case CreateUser(user) => users += user
-    case GetUser(name) => sender ! UserInfo(users.find(_.name == name))
-    case DeleteUser(name) => users.find(_.name == name) map { user => users -= 
user }
+    case GetUsers =>
+      sender ! Users(users.toSeq)
+    case CreateUser(user) =>
+      users += user
+      sender ! ActionPerformed(s"User ${user.name} created.")
+    case GetUser(name) =>
+      sender ! users.find(_.name == name)
+    case DeleteUser(name) =>
+      users.find(_.name == name) map { user => users -= user }
+      sender ! ActionPerformed(s"User ${name} deleted.")
   }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to