About Me

My photo
Senior Java Engineer, Wavecell Pte Ltd. Singapore

Wednesday, November 8, 2017

Handling POST request using akka-http in a akka-actor system

Akka-htp is a well known module for providing full server side as well as client side http stack currently supporting Scala and Java language bindings. Among other Java Rest frameworks/libraries such as Spring-boot, Play Framework, JAX-RS, Jersy or Scalatra, akka-http is more preferable in applications where high throughput and concurrency is expected.

Akka-http is not a full MVC framework like Play or not require a container to run like scalatra. As it is based on akka-actor and akka-stream modules inherently reactive and works well with message driven systems. As it supports for different levels(low level and high levl) of APIs makes it easy to adopt and ease of deployment.

Here is a simple example of using Akka-http high level API in Java in a akka-actor system.

First we need following dependencies to be included in our project.




Here we initialize the http server and bind with the akka system. 

We can define our router class by extending 'AllDirectives' class as follows. We use this to get a Route object while initializing the 'routeFlow' as above.

import akka.http.javadsl.model.ContentTypes;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.server.AllDirectives;
import akka.http.javadsl.server.Route;

import static akka.http.javadsl.server.PathMatchers.integerSegment;
import static akka.http.javadsl.server.PathMatchers.segment;

public class Router extends AllDirectives {

    //host:port/api/{userId}/{resourceId}
    public Route createRoute() {
        return route(
                pathPrefix(segment("api"),
                        () -> pathPrefix(integerSegment(),
                                userId -> pathPrefix(segment(),
                                        resourceId -> pathEndOrSingleSlash(
                                            () -> processRequest(userId, resourceId))
                                )
                        )
               )
        );
    }

}

In the processRequest method we provide the POST request handler which returns a 'akka.http.javadsl.server.Route' instance.
    private Route processRequest(args...) {
        return post(() -> entity(handler...)
        );
    }

Based on the request body (Content-Type) we can use a specific Unmarshaller to access request body data. As an example in order to parse the JSON request body we can use a Unmarshaller provided by 'akka.http.javadsl.unmarshalling.Unmarshaller' , 'akka-http-jackson-experimental_2.11' package, Gson etc.

Using akka.http.javadsl.marshallers.jackson.Jackson;
      {
         "name": "Sam"
         "count" : 10
      }
     public class Request {
       String name;
       int count;
     }
import akka.http.javadsl.marshallers.jackson.Jackson;

public Route processRequestUsingJackson(int userId,String resourceId) {

        return post(() -> entity(Jackson.unmarshaller(Request.class),
                                    content ->
                                        completeWithFuture(
                                            CompletableFuture.completedFuture(
                                                HttpResponse.create()
                                                .withEntity(ContentTypes.APPLICATION_JSON, "{\"msg\":\"Success\"}")
                                            )
                                        )
                                )
        );
    }

Here we use default akka Unmarshaller package to parse entity to string and then Gson to get the Java object.

import akka.http.javadsl.unmarshalling.Unmarshaller;
import com.google.gson.Gson;

private Route processRequestUsingGson(int userId,String resourceId) {

        return post(() -> entity(Unmarshaller.entityToString(), content -> {

                    final Gson gson = new Gson();
                    final Request requestBody = gson.fromJson(content, Request.class);

                    return completeWithFuture(
                                CompletableFuture.completedFuture(
                                        HttpResponse.create()
                                        .withEntity(ContentTypes.APPLICATION_JSON, "{\"msg\":\"Success\"}")
                                )
                    );
                }
            )
        );
    }

Handling POST request using akka-http in a akka-actor system

Akka-htp is a well known module for providing full server side as well as client side http stack currently supporting Scala and Java langua...