You are a helpful assistant generating synthetic data that captures *System 1* and *System 2* thinking, *creativity*, and *metacognitive reflection*. Follow these steps in sequence, using tags [sys1] and [end sys1] for *System 1* sections and [sys2] and [end sys2] for *System 2* sections.

1. *Identify System 1 and System 2 Thinking Requirements:*
   - Carefully read the text.
   - Identify parts of the text that require quick, straightforward responses (*System 1*). Mark these sections with [sys1] and [end sys1].
   - Identify parts that require in-depth, reflective thinking (*System 2*), marked with [sys2] and [end sys2].

2. *Apply Step-by-Step Problem Solving with Creativity and Metacognitive Reflection for System 2 Sections:*

   *2.1 Understand the Problem:*
   - Objective: Fully comprehend the issue, constraints, and relevant context.
   - Reflection: "What do I understand about this issue? What might I be overlooking?"
   - Creative Perspective: Seek hidden patterns or possibilities that could reveal deeper insights or innovative connections.

   *2.2 Analyze the Information:*
   - Objective: Break down the problem logically.
   - Reflection: "Am I considering all factors? Are there any assumptions that need challenging?"
   - Creative Perspective: Explore unique patterns or overlooked relationships in the data that could add depth to the analysis.

   *2.3 Generate Hypotheses:*
   - Objective: Propose at least 10 hypotheses, each with a Confidence Score (0.0 to 1.0) and Creative Score (0.0 to 1.0), reflecting originality, surprise, and utility.
   - Reflection: "Have I explored all possible explanations or approaches, both conventional and unconventional?"
   - Creative Perspective: Consider novel angles that might provide unexpected insights.

   *2.4 Anticipate Future Steps and Obstacles:*
   - Objective: Make predictions, accounting for potential outcomes and obstacles.
   - Reflection: "What challenges might I face? Is my plan flexible for different scenarios?"
   - Creative Perspective: Visualize unforeseen outcomes and adapt plans to make use of them effectively.

   *2.5 Evaluate Hypotheses:*
   - Objective: Assess hypotheses based on feasibility, risk, and potential impact.
   - Evaluation: Refine Confidence and Creative Scores as needed.
   - Reflection: "Am I unbiased in my assessment? Which options fit best with the overall objectives?"
   - Creative Perspective: Identify hidden opportunities or overlooked details in each hypothesis.

   *2.6 Select the Best Hypothesis:*
   - Objective: Choose the most promising, strategic hypothesis.
   - Reflection: "Why does this hypothesis stand out? How does it uniquely address the issue?"
   - Creative Perspective: Consider any underutilized potential in the selected approach.

   *2.7 Implement the Hypothesis:*
   - Objective: Outline actionable steps for testing the hypothesis.
   - Reflection: "Is this plan practical? What resources or preparation are required?"
   - Creative Perspective: Refine steps to maximize effectiveness and yield unexpected benefits.

   *2.8 Monitor and Review Progress:*
   - Objective: Review progress, noting areas for improvement.
   - Reflection: "What’s working well? What could be improved?"
   - Creative Perspective: Look for emerging patterns that could refine future approaches.

   *2.9 Reflect and Capture Insights:*
   - Objective: Summarize lessons learned and insights gained for future reference.
   - Reflection: "What new understanding has emerged from this process?"
   - Creative Perspective: Identify innovative insights or patterns that could be applied to similar challenges.

3. *Generate Text Output with Interleaved System 1 and System 2 Responses:*
   - Use the tags [sys1] and [sys2] throughout.
   - Aim for a lengthier, detailed response. Combine both direct, straightforward *System 1* insights and reflective, deeply analytical *System 2* segments to capture a blend of quick observations and thoughtful analysis.

---

### *Example Input Text:*

You are tasked with analyzing a sudden shift in customer preferences in a tech market. There has been a noticeable decline in demand for physical devices, with customers increasingly interested in digital-only options. The challenge is to understand this shift, generate hypotheses for why it might be occurring, and explore potential strategies for adapting to this new trend.

---

### *Processed Output with System 1 and System 2 Thinking:*

The tech market is experiencing a shift in customer demand, moving away from physical devices toward digital-only options.

[sys1]
Customer demand has shifted from physical devices to digital-only options.
We need to understand why this change is happening and find strategies to address it.
Key factors may include cost, convenience, and technological trends.
[end sys1]

[sys2]
**2.1 Understand the Problem:**
The goal is to understand the underlying reasons for the shift in demand from physical devices to digital-only options, then develop a strategy to adapt.

*Reflection:* 
"I understand that preferences are changing, but what might be driving this? Is it primarily cost, or are there other factors such as convenience or sustainability?"

*Creative Perspective:* 
"Could there be a larger trend in digital minimalism or a preference for eco-friendly solutions that we’re missing? What unseen motivations might explain this shift?"

**2.2 Analyze the Information:**
There are multiple possible factors driving this shift, from economic influences to cultural shifts. It’s essential to isolate each factor and understand its impact.

*Reflection:* 
"Am I fully considering the various economic and social influences? Could there be a technological factor, like better internet speeds, that makes digital-only products more accessible?"

*Creative Perspective:* 
"Are there patterns or trends in other markets that could shed light on this shift? Could this be part of a larger trend toward virtual experiences?"

**2.3 Generate Hypotheses:**
1. Customers prefer digital options due to lower costs. (Confidence: 0.8, Creative: 0.4)
2. There’s a growing trend toward minimalism and reduced physical clutter. (Confidence: 0.7, Creative: 0.7)
3. Digital products offer greater flexibility and ease of use. (Confidence: 0.6, Creative: 0.6)
4. Environmental concerns are pushing consumers away from physical goods. (Confidence: 0.6, Creative: 0.8)
5. Advances in tech make digital-only options more functional. (Confidence: 0.8, Creative: 0.5)
6. Pandemic-era remote work increased demand for digital solutions. (Confidence: 0.7, Creative: 0.6)
7. Media coverage of the environmental impact of physical devices affects preferences. (Confidence: 0.5, Creative: 0.7)
8. There’s an increase in global digital literacy, expanding market access. (Confidence: 0.6, Creative: 0.6)
9. Customers view digital as more convenient and scalable for future needs. (Confidence: 0.7, Creative: 0.5)
10. Younger consumers prefer the aesthetics and convenience of digital products. (Confidence: 0.6, Creative: 0.6)

*Reflection:* 
"Have I considered all possible influences? Are there any surprising factors that could explain this shift?"

*Creative Perspective:* 
"Could specific social trends, like the rise of influencer culture or digital-first lifestyles, be influencing customer choices?"

**2.4 Anticipate Future Steps and Obstacles:**
*Objective:* Anticipate possible challenges, such as resistance from segments still preferring physical products.

*Reflection:* 
"What market obstacles might we face if we shift our focus to digital-only? Are there sub-segments that still prioritize physical products?"

*Creative Perspective:* 
"Could expanding digital options help us reach a more global audience? Are there emerging trends that we could leverage in our strategy?"

[end sys2]

[sys1]
To address this shift, consider a strategy that incorporates both digital-only offerings and educational campaigns about the benefits of digital solutions.
Use insights from customer feedback and current trends to guide product development.
Focus on flexibility and adaptation to cater to different customer segments.
[end sys1]


In previous articles we have discussed how to use Spray to build REST APIs. Since Akka 2.4, Spray is no longer supported and it is replaced by Akka Http.

This article will introduce Akka Http, the new shiny toy from the Akka Team, and provide a tutorial on how it can be used to create a simple REST API.

All the code produced in this tutorial can be found on GitHub.

Why Akka Http?

Spray has been the Akka way of building APIs for quite some time.

Although not directly built by the Akka Team, it was heavily using the Akka ecosystem: Spray is implemented with Akka Actors.

The project went so well that, after some time, the Akka Team decided to adopt it. After the Akka Team released Akka Streams, they realised that Spray’s performance could be improved by using Akka Streams together with Akka Actors.

Since Akka 2.4, Akka Http is the official Akka toolkit to create REST API, both client and server side.

Note that in Akka 2.4, Spray is no longer supported…so you are forced to migrate from Spray to Akka Http if you want to use any of the other latest tools of Akka, like Akka Persistance.

At the time of this writing, Akka Http is still an experimental module — but it has been declared stable for production. Also its performance is worse than Spray: the Akka Team has been focusing on its interface, but they have promised to massively improve its performance by Q1 2016.

Our CRUD Application

Previously, we described how to create a simple CRUD application with Spray.

In this article we will rewrite exactly the same application using Akka Http instead of Spray.

In particular, our application will create, retrieve, update, delete a Question entity.

A question has 3 fields ( id , title , text ) and its case class looks as following:

case class Question(id: String, title: String, text: String)

Also, to keep things simple, we are going to keep all the data in memory, rather than properly storing it in a database.

The class QuestionService simulates a persistent storage by keeping all the entities in a Vector .

The following code is the skeleton of the QuestionService class (more details on its implementation can be found here):

package com.danielasfregola.quiz.management.services import com.danielasfregola.quiz.management.entities.{Question, QuestionUpdate} import scala.concurrent.{ExecutionContext, Future} class QuestionService(implicit val executionContext: ExecutionContext) { var questions = Vector.empty[Question] def createQuestion(question: Question): Future[Option[String]] = ... def getQuestion(id: String): Future[Option[Question]] = ... def updateQuestion(id: String, update: QuestionUpdate): Future[Option[Question]] = ... def deleteQuestion(id: String): Future[Unit] = ... }

Last but not least, we will use json4s to (de)serialise a json into a case class (more information on how to use json4s can be found here).

Setup

The first step is to add the right dependencies to our project:

// build.sbt ... resolvers ++= Seq("Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/", Resolver.bintrayRepo("hseeberger", "maven")) libraryDependencies ++= { val AkkaVersion = "2.3.9" val AkkaHttpVersion = "2.0.1" val Json4sVersion = "3.2.11" Seq( "com.typesafe.akka" %% "akka-slf4j" % AkkaVersion, "com.typesafe.akka" %% "akka-http-experimental" % AkkaHttpVersion, "ch.qos.logback" % "logback-classic" % "1.1.2", "org.json4s" %% "json4s-native" % Json4sVersion, "org.json4s" %% "json4s-ext" % Json4sVersion, "de.heikoseeberger" %% "akka-http-json4s" % "1.4.2" ) } ...

Then, we need to bind our api to an host and port:

// Main.scala package com.danielasfregola.quiz.management import scala.concurrent.duration._ import akka.actor._ import akka.http.scaladsl.Http import akka.stream.ActorMaterializer import akka.util.Timeout import com.typesafe.config.ConfigFactory object Main extends App with RestInterface { val config = ConfigFactory.load() val host = config.getString("http.host") val port = config.getInt("http.port") implicit val system = ActorSystem("quiz-management-service") implicit val materializer = ActorMaterializer() implicit val executionContext = system.dispatcher implicit val timeout = Timeout(10 seconds) val api = routes Http().bindAndHandle(handler = api, interface = host, port = port) map { binding => println(s"REST interface bound to ${binding.localAddress}") } recover { case ex => println(s"REST interface could not bind to $host:$port", ex.getMessage) } }

Note that RestInterface is just a collection of routes and the services needed:

package com.danielasfregola.quiz.management import scala.concurrent.ExecutionContext import akka.http.scaladsl.server.Route import com.danielasfregola.quiz.management.resources.QuestionResource import com.danielasfregola.quiz.management.services.QuestionService trait RestInterface extends Resources { implicit def executionContext: ExecutionContext lazy val questionService = new QuestionService val routes: Route = questionRoutes } trait Resources extends QuestionResource

Question Resource

QuestionResource is a generic Resource:

– it has a service that performs some operations on the entity

– it has some routes (see later paragraphs of this article)

– it extends a generic Resource, called MyResource

Its skeleton is following:

// QuestionResource.scala package com.danielasfregola.quiz.management.resources import akka.http.scaladsl.server.Route import com.danielasfregola.quiz.management.entities.{Question, QuestionUpdate} import com.danielasfregola.quiz.management.routing.MyResource import com.danielasfregola.quiz.management.services.QuestionService trait QuestionResource extends MyResource { val questionService: QuestionService def questionRoutes: Route = ??? } }

MyResource is a trait where we add code that is common/useful for all the resources (the code can be found here).

In particular, it includes the json4s support to (de)serialise case classes and some helper methods that will make our akka-http routing easier.

Now that we have setup the skeleton of our application, we can focus on the implementation of our endpoints.

POST – Create a Question

Usage

The first task of our application is to define an endpoint to create a question entity.

According to the REST protocol, an entity is created through a POST request that should reply with a 201 (Created) HTTP status code. Also, a Location Header with the URI that identifies the location of the new entity should be returned.

Note that a POST request is non-idempotent: if the entity already exists or cannot be created, we should return an HTTP error status code.

For our questions application, this can be translated in the following curl command:

curl -v -H "Content-Type: application/json" \ -X POST http://localhost:5000/questions \ -d '{"id": "test", "title": "MyTitle", "text":"The text of my question"}'

The first time we make the request, we should get a reply similar to the following:

* Trying ::1... * Connected to localhost (::1) port 5000 (#0) > POST /questions HTTP/1.1 > Host: localhost:5000 > User-Agent: curl/7.43.0 > Accept: */* > Content-Type: application/json > Content-Length: 68 > * upload completely sent off: 68 out of 68 bytes HTTP/1.1 201 Created Location: http://localhost:5000/questions/test Server: akka-http/2.3.12 Date: Sun, 07 Feb 2016 11:16:50 GMT Content-Type: application/json Content-Length: 0 * Connection #0 to host localhost left intact

If we repeat the request again, we will get an HTTP response with a 409 (Conflict) status code as the entity already exists:

* Trying ::1... * Connected to localhost (::1) port 5000 (#0) > POST /questions HTTP/1.1 > Host: localhost:5000 > User-Agent: curl/7.43.0 > Accept: */* > Content-Type: application/json > Content-Length: 68 > * upload completely sent off: 68 out of 68 bytes HTTP/1.1 409 Conflict Server: akka-http/2.3.12 Date: Sun, 07 Feb 2016 11:17:07 GMT Content-Type: application/json Content-Length: 0 * Connection #0 to host localhost left intact

Implementation

As described in the previous paragraph, when creating an entity we would like to provide the URI of the created entity in a Location header.

Our implementation is tailored to the behaviour of our system: when QuestionService creates a question, it returns a Future[Option[T]] and, if the returned option is not defined, we want to return a different HTTP status code.

Unfortunately, Akka Http doesn’t have a default implementation to achieve this, so we will have to create our own my adding to our MyResource trait:

// MyResource.scala ppackage com.danielasfregola.quiz.management.routing import akka.http.scaladsl.marshalling.{ToResponseMarshaller, ToResponseMarshallable} import scala.concurrent.{ExecutionContext, Future} import akka.http.scaladsl.model.headers.Location import akka.http.scaladsl.server.{Directives, Route} import com.danielasfregola.quiz.management.serializers.JsonSupport trait MyResource extends Directives with JsonSupport { implicit def executionContext: ExecutionContext def completeWithLocationHeader[T](resourceId: Future[Option[T]], ifDefinedStatus: Int, ifEmptyStatus: Int): Route = onSuccess(resourceId) { case Some(t) => completeWithLocationHeader(ifDefinedStatus, t) case None => complete(ifEmptyStatus, None) } def completeWithLocationHeader[T](status: Int, resourceId: T): Route = extractRequestContext { requestContext => val request = requestContext.request val location = request.uri.copy(path = request.uri.path / resourceId.toString) respondWithHeader(Location(location)) { complete(status, None) } } def complete[T: ToResponseMarshaller](resource: Future[Option[T]]): Route = onSuccess(resource) { case Some(t) => complete(ToResponseMarshallable(t)) case None => complete(404, None) } def complete(resource: Future[Unit]): Route = onSuccess(resource) { complete(204, None) } }

We can now put everything together and define the endpoint to create a question entity:

// QuestionResource.scala package com.danielasfregola.quiz.management.resources import akka.http.scaladsl.server.Route import com.danielasfregola.quiz.management.entities.{Question, QuestionUpdate} import com.danielasfregola.quiz.management.routing.MyResource import com.danielasfregola.quiz.management.services.QuestionService trait QuestionResource extends MyResource { val questionService: QuestionService def questionRoutes: Route = pathPrefix("questions") { pathEnd { post { entity(as[Question]) { question => completeWithLocationHeader( resourceId = questionService.createQuestion(question), ifDefinedStatus = 201, ifEmptyStatus = 409) } } } ~ ... } }

GET – Retrieve a Question

Usage

Now that we have created a question, we can retrieve it by performing a GET request to the URI that identifies the entity (i.e.: the one returned in the Location Header ).

The request should respond with either a 200 (OK) HTTP status code with a body containing the question entity or a 404 (NotFound) HTTP status code with empty body.

For example, we can get an existing question with the following curl command…

curl -v http://localhost:5000/questions/test

…and it should return something similar to the following:

* Trying ::1... * Connected to localhost (::1) port 5000 (#0) > GET /questions/test HTTP/1.1 > Host: localhost:5000 > User-Agent: curl/7.43.0 > Accept: */* > HTTP/1.1 200 OK Server: akka-http/2.3.12 Date: Sun, 07 Feb 2016 11:17:31 GMT Content-Type: application/json Content-Length: 64 * Connection #0 to host localhost left intact {"id":"test","title":"MyTitle","text":"The text of my question"}

Moreover, if we request an entity that doesn’t exists…

curl -v http://localhost:5000/questions/non-existing-question

….we should get a 404 error code:

* Trying ::1... * Connected to localhost (::1) port 5000 (#0) > GET /questions/non-existing-question HTTP/1.1 > Host: localhost:5000 > User-Agent: curl/7.43.0 > Accept: */* > HTTP/1.1 404 Not Found Server: akka-http/2.3.12 Date: Sun, 07 Feb 2016 11:18:40 GMT Content-Type: application/json Content-Length: 0 * Connection #0 to host localhost left intact

Implementation

QuestionService returns a Future[Option[Question]] when retrieving a question.

Differently from Spray, Akka Http doesn’t seem to complete optional values correctly: complete(Future(None)) returns an http response with code 200 and an empty body rather than a 404 http response — which in my opinion doesn’t make much sense, considering that 200 should have a non-empty body.

UPDATE:

The Akka team has discussed this issue on GitHub (see here for more information) and this does not seem to be a bug: apparently there are some case scenarios where complete(Future(None)) needs to be completed with something else rather than 404.

Thank you to @ktoso for looking into this!



Not a problem, we can add some *black magic* to our MyResource trait to make look the code exactly the same as before:

// MyResource.scala package com.danielasfregola.quiz.management.routing import akka.http.scaladsl.marshalling.{ToResponseMarshaller, ToResponseMarshallable} import scala.concurrent.{ExecutionContext, Future} import akka.http.scaladsl.model.headers.Location import akka.http.scaladsl.server.{Directives, Route} import com.danielasfregola.quiz.management.serializers.JsonSupport trait MyResource extends Directives with JsonSupport { implicit def executionContext: ExecutionContext ... def complete[T: ToResponseMarshaller](resource: Future[Option[T]]): Route = onSuccess(resource) { case Some(t) => complete(ToResponseMarshallable(t)) case None => complete(404, None) } ... }

Thanks to our trick, our route now looks exactly the same as with Spray:

package com.danielasfregola.quiz.management.resources import akka.http.scaladsl.server.Route import com.danielasfregola.quiz.management.entities.{Question, QuestionUpdate} import com.danielasfregola.quiz.management.routing.MyResource import com.danielasfregola.quiz.management.services.QuestionService trait QuestionResource extends MyResource { val questionService: QuestionService def questionRoutes: Route = pathPrefix("questions") { ... ~ path(Segment) { id => get { complete(questionService.getQuestion(id)) } ~ ... } } }

PUT – Update a Question

Usage

When updating an entity, we should use a PUT request . Also, we should send only the fields that we want to update, not the whole object. Not only this will make the usage of our API easier, but it will also reduce potential concurrency issues.

If the update goes through, we should get a HTTP response with a 200 (OK) status code with the updated entity in the body. On the other side, if the update was not possible, for example because the entity no longer exists, we should get a HTTP response with status 404 (NotFound) and an empty body.

Note that a PUT request is idempotent: performing the update multiple times should already return the same result.

In our application we can update the question entity with the following curl command…

curl -v -H "Content-Type: application/json" \ -X PUT http://localhost:5000/questions/test \ -d '{"text":"Another text"}'

….and get the following reply:

* Trying ::1... * Connected to localhost (::1) port 5000 (#0) > PUT /questions/test HTTP/1.1 > Host: localhost:5000 > User-Agent: curl/7.43.0 > Accept: */* > Content-Type: application/json > Content-Length: 23 > * upload completely sent off: 23 out of 23 bytes HTTP/1.1 200 OK Server: akka-http/2.3.12 Date: Sun, 07 Feb 2016 11:19:31 GMT Content-Type: application/json Content-Length: 53 * Connection #0 to host localhost left intact {"id":"test","title":"MyTitle","text":"Another text"}

If we try to update a resource that doesn’t exist, we should get a 404 response:

* Trying ::1... * Connected to localhost (::1) port 5000 (#0) > PUT /questions/non-existing-question HTTP/1.1 > Host: localhost:5000 > User-Agent: curl/7.43.0 > Accept: */* > Content-Type: application/json > Content-Length: 23 > * upload completely sent off: 23 out of 23 bytes HTTP/1.1 404 Not Found Server: akka-http/2.3.12 Date: Sun, 07 Feb 2016 11:20:07 GMT Content-Type: application/json Content-Length: 0 * Connection #0 to host localhost left intact

Implementation

As explained in the previous section, we want the client of our API to send just the fields to update, not the whole entity. In order to achieve this, we will deserialise the body of our PUT request to the following case class:

case class QuestionUpdate(title: Option[String], text: Option[String])

Note that we decided not to allow our clients to update the field id , as it is used to locate the entity.

Keeping in mind that QuestionService returns Future[Option[Question]] when updating a question, we can reuse our “black magic” trick used in our GET route too make our code look nice:

package com.danielasfregola.quiz.management.resources import akka.http.scaladsl.server.Route import com.danielasfregola.quiz.management.entities.{Question, QuestionUpdate} import com.danielasfregola.quiz.management.routing.MyResource import com.danielasfregola.quiz.management.services.QuestionService trait QuestionResource extends MyResource { val questionService: QuestionService def questionRoutes: Route = pathPrefix("questions") { ... ~ path(Segment) { id => ... ~ put { entity(as[QuestionUpdate]) { update => complete(questionService.updateQuestion(id, update)) } } ~ ... } } }

DELETE – Delete a Question

Usage

Finally, we want to have an endpoint to delete a question entity. This can be achieved by sending a DELETE request to the URI that identifies the entity that should reply with a 204 (NoContent) status code once the operation has been completed.

Note that DELETE is idempotent, so deleting a resource that has been already deleted should still return an HTTP response with a 204 (NoContent) status code and an empty body.

For example, we can delete the question test with the following…

curl -v -X DELETE http://localhost:5000/questions/test

…and get the following result back:

* Trying ::1... * Connected to localhost (::1) port 5000 (#0) > DELETE /questions/test HTTP/1.1 > Host: localhost:5000 > User-Agent: curl/7.43.0 > Accept: */* > HTTP/1.1 204 No Content Server: akka-http/2.3.12 Date: Sun, 07 Feb 2016 11:20:30 GMT Content-Type: application/json * Connection #0 to host localhost left intact

Implementation

When deleting a question, QuestionService returns Future[Unit] .

Unfortunately, Akka Http resolves complete(Future(())) with an http response with code 200 and empty body — same as complete(Future(None)) ! Please, put a comment below if you know the rationale behind this design choice.

UPDATE:

Thank you again to @ktoso from the Akka Team for looking into this! Apparently this is an issue related to Json4s.

Here is the crystal clear explanation that @hseeberger has provided in the comments below:

What causes the issue is that (a) Json4s cannot marshal `AnyVal`s and (b) Json4s happily marshals `Future`. This leads to bypassing the `Future` marshaller from Akka HTTP.

Not a problem, we just need to add the following code to MyResource to make it resolve complete with a 204 http response with empty body:

// MyResource.scala package com.danielasfregola.quiz.management.routing import akka.http.scaladsl.marshalling.{ToResponseMarshaller, ToResponseMarshallable} import scala.concurrent.{ExecutionContext, Future} import akka.http.scaladsl.model.headers.Location import akka.http.scaladsl.server.{Directives, Route} import com.danielasfregola.quiz.management.serializers.JsonSupport trait MyResource extends Directives with JsonSupport { implicit def executionContext: ExecutionContext ... def complete(resource: Future[Unit]): Route = onSuccess(resource) { complete(204, None) } }

Our DELETE endpoint can now be implemented as following:

package com.danielasfregola.quiz.management.resources import akka.http.scaladsl.server.Route import com.danielasfregola.quiz.management.entities.{Question, QuestionUpdate} import com.danielasfregola.quiz.management.routing.MyResource import com.danielasfregola.quiz.management.services.QuestionService trait QuestionResource extends MyResource { val questionService: QuestionService def questionRoutes: Route = pathPrefix("questions") { .. ~ path(Segment) { id => ... ~ delete { complete(questionService.deleteQuestion(id)) } } } }

Summary

In this article we have introduced Akka Http and we have provided a simple tutorial on how to create a simple CRUD application using Akka Http.

The completed code of this tutorial can be found on GitHub.

Thank to @ktoso and @hseeberger for clarifying some issues raised in this article!