DataKernel 3.0 — Getting Started With New Full-stack Java Framework

Valeria Listratova
SoftIndex
Published in
6 min readNov 6, 2019

The ambitious Java framework DataKernel has finally reached the 3.0 version release. This is the first release for general audience. Previously, it was used only as an in-house technology for an ad-tech solution AdKernel, where DataKernel proved its efficiency in real-life high-load application, processing billions of requests daily.

The new “Alternative to Spring” aims to provide a high-level minimalistic programming approach for creating all kinds of applications, from simple web apps to high-performance scalable backend microservices solutions, with legacy-free approach and no speed compromises. Can it make other Java frameworks obsolete? Let’s find out!

What it’s all about?

DataKernel is an asynchronous Java framework with a full application stack. Its main advantage is that it is built from the ground up, without the overhead of intermediate adapters over abstractions and legacy standards of third-party libraries. Its components are tailored perfectly to each other — from core I/O and DI to big-data, which makes the framework minimalistic, streamlined and lightning-fast:

Benchmarks of DataKernel components compared to similar solutions

Nevertheless, the raw speed isn’t the only advantage of DataKernel. The coolest thing is that you won’t need to worry about integration of diverse frameworks, libraries, etc in your project anymore, as DataKernel is an all-in-one solution. This also means that prototyping and subsequent scaling can be implemented consistently within one framework ecosystem.

DataKernel 3.0 — what’s inside

The first thing to notice is that DataKernel consists of loosely coupled components. In other words, you can use different modules as stand-alone plugins for your projects or combine them according to your needs.

Let’s start with more common components first.

DataKernel has its own dependency injection implementation with a set of powerful tools: nested scopes, multithreaded and single-threaded modes, object factories, modules and plugins for transforming dependencies graph at startup time, abstracting out all reflection. What’s fascinating is that it is 5 times faster than Guice and 100 times faster than Spring. DI has zero dependencies, so you can use it as a stand-alone component.

Also, DataKernel provides the ability to establish an asynchronous data transfer between HTTP servers and clients with up to 185K RPS on a single core, which is even faster than highly specialized Vert.x. The framework includes a set of built-in asynchronous servlets to simplify and speed up the development.

DataKernel was inspired by Node.js asynchronous model, so it has its own Promise (efficient Java Futures alternative with up to 100M RPS) and Eventloop which includes asynchronous I/O operators, multithreading and a task scheduler.

Now let’s get to the hot stuff!

As an alternative to low-level Netty, DataKernel provides a module called Net, with a high-level and simple programming model. It handles socket connections and ensures low performance overhead thanks to Promises and CSP compatibility. CSP (Communicating Sequential Process) was implemented similar to the Go approach but with improved performance. It enables I/O communication between individual processes via channels. Another module, Datastream, ensures overhead-free intra and inter-server communication.

Comparison of Datastream and CSP modules

Particularly noteworthy is the Codegen module that provides a solution for runtime creation of methods and classes. In fact, it is an embedded Lisp with a codegen and automatic type inference. Its runtime-generated code works as fast as a manually written. Features an expression-based API to avoid the complexity of direct bytecode manipulation.

For distributed applications there’s the ultra high-performance binary RPC. It provides a more efficient connection with up to 15M requests per second on a single core and built-in RPC strategies (First Available, Round-Robin, Rendezvous Hashing, etc), which can be simply combined.

The release includes a set of benchmarks to showcase the impeccable performance of various modules. Feel free to check them out:

DataKernel — Getting started

I guess you’re thinking: “It’s all pretty amazing, but what about usability and under the hood restrictions?”. Worry not: DataKernel is quite a simple and intuitive framework and resembles Node.js approach, particularly when it comes to developing HTTP servers.

Let’s go through a short starting guide based on the DataKernel HTTP module. As you might have already guessed, we’ll create an HTTP “Hello World!” server.

First of all, let’s get the mandatory tools installed:

  1. JDK 1.8+;
  2. Your favorite IDE;
  3. Maven to import the required jar files; refer to installation guide for the setup;

Now, we can either be lazy and generate the working example using archetypes, or create a new project from scratch.

Let’s consider the easy way first

Using archetypes: To generate a project in a directory, open a terminal and type in the following command:

All that’s left is to open the project in your IDE and run main method in the WebApp class. To see the “Hello World!” message, open a browser and go to localhost:8080.

Congratulations, your server is ready! You can find the implementation details a little further.

If you’d like to do everything manually instead, here’s a step-by-step guide

  • Create a new Maven project in your IDE;
  • Add the following Maven dependencies:
  • Make sure to import them after they’re added.
  • Create a new HttpHelloWorldExample class in your src directory and write the following code into it:
  • After you run main, open a browser and go to localhost:8080 to see the “Hello, World!” message.

Congratulations, you’ve just created your first DataKernel app! Wasn’t that difficult, right?

How does it work?

The first thing you’ll notice is the HttpServerLauncher superclass. It is a part of the Launchers module. Launchers manage an app’s full lifecycle: they inject dependencies, start the application, run it and stop it, providing you with the necessary logs along the way. Seems much easier than doing all of that by yourself, huh?

The following line introduces you to the @Provides annotation, which is an essential part of the DataKernel DI module. It signals that the following servlet will be created and integrated as the root HTTP endpoint listener via DI. This way you don’t have to create and pass the instance manually.

Next, the asynchronous servlet: it receives an HTTP request from clients and sends an HTTP response. To define the response, we override the AsyncServlet.serve method with lambda. Here goes your first Promise: in lambda we create a Promise of HttpResponse with code 200 and “Hello, World!” body. Promises are a high-performance alternative to Java Futures for representing a result of an asynchronous computation.

Lastly, we create an instance of our class in main and start our server via launch method that implements the Launcher’s functionality mentioned before. Yep, that’s it — you just got a functional HTTP server in 10 lines of code with all the processes explained in 4 short paragraphs. Clear, clean and effective — isn’t that neat?

Of course, that’s only a glimpse of what DataKernel has to offer. Check out detailed tutorials and examples on DataKernel website.

If you have any questions, feel free to contact us on Twitter and GitHub! Happy coding!

--

--

Valeria Listratova
SoftIndex

I’m a technical content writer who is interested in Java and new technologies