Build a Simple Netty Application With and Without Spring
Build a Simple Netty Application With and Without Spring
In this article, we discuss how to build a Netty application with and without Spring to better understand just how much Spring abstracts for us.
Join the DZone community and get the full member experience.Join For Free
As an asynchronous, non-blocking input/output (NIO) framework, Netty is used for the rapid development of maintaining highly scalable protocol servers & clients. Building low-level network servers and clients is relatively straightforward with Netty. Developers can work on the socket level, such as creating original communication protocols between clients and servers.
Blocking and non-blocking unified APIs, amenable threading model, and SSL/TLS are all supported by Netty. All requests run asynchronously on an individual thread with a non-blocking server (the event loop shouldn’t be blocked by the function). This contradicts with a blocking server model, which usually uses a separate thread to run each request. Without the need for switching or creating threads when the load increases, the non-blocking model decreased overhead and faster development as traffic expands.
All of this power, however, comes at the cost of complexity. Non-blocking code is typically harder to read, to test, and to maintain, although this has improved greatly as the asynchronous paradigm has matured. Since Netty works at the socket level, it also requires a deeper understanding of the nuts and bolts of things like thread loops, byte buffers, and memory management.
The Netty.io team has done an admirable job of making Netty easy to use for all its power, but it’s still necessarily more complicated than higher-level libraries (such as Spring Boot WebFlux). So why use it?
Netty is designed to make the implementation of custom network protocols relatively easy. HTTP is great, but its a general-purpose protocol, basically well-suited to most things. But if you’re consistently passing custom, structured data back and forth between servers and clients (large files, streaming media, real-time game data, etc…), you can do better. Netty allows you to write your own network protocol tailored to your specific requirements, optimizing the traffic flow for your specific situation, without the unnecessary overhead of something like HTTP or FTP.
However, even if you’re not going to write your own custom TCP protocol, you can still use the power of Netty. Spring WebFlux is Spring’s answer to non-blocking and reactive programming. It’s an alternative to the traditional (blocking) Spring MVC architecture. By default, the Spring Boot WebFlux Starter runs on an embedded Netty server. In this configuration, you can think of WebFlux as a reactive, non-blocking HTTP application layer built on top of Netty’s NIO socket goodness.
In this tutorial, you are going to create a basic “Hello world” application in Netty. Next, you’re going to create the same “Hello world” application in Spring Boot WebFlux. Finally, you’re going to add OAuth 2.0 login to the application using Okta as the OAuth 2.0 provider.
This project has a few required tools to install before you get started.
HTTPie: This is a simple command-line utility for making HTTP requests that you’ll use to test the REST application. It’s also beloved by Okta developers. Install per the instructions on their website.
Okta Developer Account: You’ll use Okta as an OAuth/OIDC provider to add OAuth2 login authentication to the application. Sign up for a free Okta developer account, if you haven’t already.
You should also go ahead and clone this blog’s GitHub repository.
The project contains three subdirectories, corresponding to the three sections of this tutorial:
netty-hello-world: a very basic example of how to create a Netty server
webflux-hello-world: how to create the same server in Spring WebFlux
webflux-oauth2login: an example of how to add OAuth2 login to a Spring WebFlux application
HTTP servers are application-layer implementations of the HTTP protocol (OSI Layer 7), so relatively high up in the internet stack. If you’re developing a REST API, you’re developing on top of an API that provides this implementation for you. By contrast, Netty doesn’t necessarily structure communication, provide session management, or even offer security like TLS. This is great if you’re building a super low-level networking application; however, perhaps not the best choice if you’re building a REST service.
Fortunately, the Netty API also provides some helper classes and functions that will allow us to easily integrate a higher level protocol like HTTP. In this part of the tutorial, you’ll use those to make a simple HTTP server.
netty-hello-world project in your favorite IDE or text editor.
First, take a look at the
src/main/java/com/okta/netty/AppServer.java file. This class is the entry point for the application and sets up the Netty server.
The most important line is
.childHandler(new ServerInitializer()), which creates
ServerHandler and hooks into the Netty server.
Next, look at
src/main/java/com/okta/netty/ServerInitializer.java. This class configures the Netty channel that will handle our requests and connects it to the
Finally, there is
src/main/java/com/okta/netty/ServerHandler.java. This is where the actual request is mapped, and the response is generated.
In this class, notice that you must convert the response string to a byte buffer. You actually generate an HTTP response and set some headers directly. This is the application layer of the internet (OSI Layer 7). When you call
ctx.write(response), it sends the response as a byte stream over TCP. The Netty team has done a great job of hiding a ton of complexity from us while staying at a low-level transport protocol.
To test this Netty app, from the project root directory
Once the application finished loading, from a separate shell, use HTTPie to perform a GET request:
That’s a simple HTTP server built in Netty. Next, you will climb the ladder of abstraction a rung and use Spring Boot and WebFlux to simplify things.
As I mentioned previously, WebFlux is a non-blocking alternative to Spring MVC. It supports reactive programming with its event-driven, asynchronous, and non-blocking approach to request handling. It also provides many functional APIs. Reactor, a reactive, server-side Java library developed in close collaboration with Spring, provides the reactive streams aspect of WebFlux. However, you could also use other reactive streams libraries.
Recall that, by default, the Spring Boot WebFlux starter runs on a Netty server. You’ll notice how much complexity Spring Boot hides from you in the next example.
The Spring Boot WebFlux project is located in the
webflux-hello-world sub-directory of the GitHub repository. It’s beguilingly simple.
Take a look at the
ReactiveApplication class. It’s the bare-bones, standard Spring Boot application class. It simply leverages the
public static void main() method and the
@SpringBootApplication to start the whole Spring Boot application framework.
ReactiveRouter is a simple router class that links HTML endpoints with handler methods. You can see that it uses dependency injection to pass the
ReactiveHandler to the router bean, which defines a single endpoint for the
ReactiveHandler is similarly simple. It defines one handler function that returns plain text. The
Mono<ServerResponse> return type is a special type for returning a stream of one element. Take a look at the Spring Docs on Understanding Reactive types to learn more about return types. If you’re used to Spring MVC, this will likely be one of the more unfamiliar aspects of WebFlux.
Open a shell and navigate to the
webflux-hello-world sub-directory of the project.
Run the project using:
Open another shell to test the endpoint with
See how much simpler Spring Boot was to use than Netty?
Next, you will secure the application using OAuth 2.0 login. This might sound complicated, but don’t worry. Spring and Okta have conspired to make it pretty darn simple!
Okta is a SaaS (software-as-service) authentication and authorization provider. We provide free accounts to developers so you can develop OIDC apps without fuss. Head over to developer.okta.com and sign up for an account.
After you’ve verified your email, log in and perform the following steps (if it’s your first time to log in, you may need to click the yellow Admin button to get to the developer dashboard):
- Go to Application > Add Application.
- Select application type Web and click Next.
- Give the app a name. I named mine “WebFlux OAuth”.
- Under Login redirect, URIs change the value to
http://localhost:8080/login/oauth2/code/okta. The rest of the default values will work.
- Click Done.
Take note of the Client ID and Client Secret at the bottom. You’ll need them in a moment.
Once you’ve created the OIDC application on Okta, you need to make a few updates in the project. If you want to skip ahead the finished project for this part of the tutorial can be found in the
webflux-oauth2login sub-directory, but I’m going to show you how to modify the
webflux-hello-world to add login.
First, add the Okta Spring Boot Starter to the Gradle build file. We’ve worked hard to make this as easy as possible, and the Okta Spring Boot Starter simplifies OAuth configuration. Take a look at the GitHub project for the starter for more info.
Add the following dependency to the dependency block of your
Next, add the following properties to the
src/main/resources/application.properties file. You need to replace the values in brackets with your own Okta domain and client ID.
You can find your Issuer URI by opening your Okta developer dashboard and going to API > Authorization Servers and looking in the table at the default server. The client ID and secret come from the OIDC application you created just a moment ago.
Now run the application:
Either log out of your Okta developer account or use an incognito window and navigate to (in a browser): http://localhost:8080.
You’ll be directed to log in using your Okta account.
Once you’ve logged in, you’ll be redirected back to the app. Yay - success!
In this tutorial, you created a basic “Hello world” application using Netty. You saw how Netty is a super-powerful framework for creating TCP and UDP network protocols. You saw how it supports non-blocking IO, and how Spring WebFlux builds on top of Netty to provide a reactive, non-blocking HTTP application framework. You then built a “Hello world” application in WebFlux, after which you used Okta as an OAuth 2.0 / OIDC provider to add OAuth 2.0 login to the application.
You can see the completed code for this tutorial on GitHub at oktadeveloper/okta-netty-webflux-example.
In addition to WebFlux, some powerful networking frameworks are built on top of Netty. Apple recently open-sourced ServiceTalk, a reactive microservices client/server library that supports HTTP, HTTP/2, and gRPC. There’s also Armeria, an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift, and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices.
If you’re interested in learning more about Spring Boot, Spring WebFlux, and OAuth 2.0, check out these useful tutorials:
- Get Started with Spring Boot, OAuth 2.0, and Okta
- Build Reactive APIs with Spring WebFlux
- What the Heck is OAuth?
- Get Started with Spring Security 5.0 and OIDC
- Identity, Claims, & Tokens – An OpenID Connect Primer, Part 1 of 3
- Build a Secure API with Spring Boot and GraphQL
A Quick Quide to Java on Netty was originally published on Okta Developer Blog on November 25, 2019.
Published at DZone with permission of Andrew Hughes , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.