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.
Java 11
: This project uses Java 11. You can install OpenJDK via the instructions found on the
OpenJDK website
or using
SDKMAN
.
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.
Open the
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
ServerInitializer
and
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
ServerHandler
.
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
netty-hello-world
, run:
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.
src/main/java/com/okta/webflux/app/ReactiveApplication.java
The
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
/
route.
src/main/java/com/okta/webflux/app/ReactiveRouter.java
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:
./gradlew bootRun
.
Open another shell to test the endpoint with
http :8080
.
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
build.gradle
file:
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:
./gradlew bootRun
.
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
If you have any questions about this post, please add a comment below. For more awesome content, follow
@oktadev on Twitter
, or subscribe to
our YouTube channel
!
A Quick Quide to Java on Netty
was originally published on Okta Developer Blog on November 25, 2019.
How to Implement Two-Factor Authentication in A Spring Boot OAuth Server? Part 2: Under the Hood
Spring Security Oauth2: Google Login