Chapter 2. Your first Netty application

This chapter covers

  • Setting up the development environment
  • Writing an Echo server and client
  • Building and testing the applications

In this chapter we’ll show you how to build a Netty-based client and server. The applications are simple—the client sends messages to the server, and the server echoes them back—but the exercise is important for two reasons.

First, it will provide a test bed for setting up and verifying your development tools and environment, which is essential if you plan to work with the book’s sample code in preparation for your own development efforts.

Second, you’ll acquire hands-on experience with a key aspect of Netty, touched on in the previous chapter: building application logic with ChannelHandlers. This will prepare you for the in-depth study of the Netty API we’ll begin in chapter 3.

2.1. Setting up the development environment

To compile and run the book’s examples, the only tools you need are the JDK and Apache Maven, both freely available for download.

We’ll also assume that you’re going to want to tinker with the example code and soon start writing your own. Although you can get by with a plain text editor, we strongly recommend the use of an integrated development environment (IDE) for Java.

2.1.1. Obtaining and installing the Java Development Kit

Your OS may already have a JDK installed. To find out, type the following on the command line:

javac -version

If you get back javac 1.7... or 1.8... you’re all set and can skip this step.[1]

1

A restricted feature set of Netty will run with JDK 1.6 but JDK 7 or higher is required for compilation, as well as for running the latest version of Maven.

Otherwise, get version 8 of the JDK from http://java.com/en/download/manual.jsp. Be careful to download the JDK and not the Java Runtime Environment (JRE), which can run Java applications but not compile them. An installer executable is provided for each platform. Should you need installation instructions, you’ll find them on the same site.

It’s a good idea to do the following:

  • Set the environment variable JAVA_HOME to the location of your JDK installation. (On Windows, the default will be something like C:Program FilesJava jdk1.8.0_60.)
  • Add %JAVA_HOME%in (${JAVA_HOME}/bin on Linux) to your execution path.

2.1.2. Downloading and installing an IDE

The following are the most widely used Java IDEs, all freely available:

All three have full support for Apache Maven, the build tool we’ll use. NetBeans and Intellij are distributed as installer executables. Eclipse is usually distributed as a zip archive, although there are a number of customized versions that have self-installers.

2.1.3. Downloading and installing Apache Maven

Even if you’re already familiar with Maven, we recommend that you at least skim this section.

Maven is a widely used build-management tool developed by the Apache Software Foundation (ASF). The Netty project uses it, as do this book’s examples. You don’t need to be a Maven expert to build and run the examples, but if you want to expand on them, we recommend reading the Maven introduction in the appendix.

Do you need to install Maven?

Eclipse and NetBeans come with an embedded Maven installation that will work fine for our purposes out of the box. If you’ll be working in an environment that has its own Maven repository, your administrator probably has a Maven installation package preconfigured to work with it.

At the time of this book’s publication, the latest Maven version was 3.3.3. You can download the appropriate tar.gz or zip file for your system from http://maven.apache.org/download.cgi. Installation is simple: extract the contents of the archive to any folder of your choice (we’ll call this <install_dir>). This will create the directory <install_dir>apache-maven-3.3.3.

As with the Java environment,

  • Set the environment variable M2_HOME to point to <install_dir>apache-maven-3.3.3.
  • Add %M2_HOME%in (or ${M2_HOME}/bin on Linux) to your execution path.

This will enable you to run Maven by executing mvn.bat (or mvn) on the command line.

2.1.4. Configuring the toolset

If you have set the JAVA_HOME and M2_HOME system variables as recommended, you may find that when you start your IDE it has already discovered the locations of your Java and Maven installations. If you need to perform manual configuration, all the IDE versions we’ve listed have menu items for setting these variables under Preferences or Settings. Please consult the documentation for details.

This completes the setup of your development environment. In the next sections we’ll present the details of the first Netty applications you’ll build, and we’ll get deeper into the framework APIs. After that you’ll use the tools you’ve just set up to build and run the Echo server and client.

2.2. Netty client/server overview

Figure 2.1 presents a high-level view of the Echo client and server you’ll be writing. While your main focus may be writing web-based applications to be accessed by browsers, you’ll definitely gain a more complete understanding of the Netty API by implementing both the client and server.

Figure 2.1. Echo client and server

Although we’ve spoken of the client, the figure shows multiple clients connected simultaneously to the server. The number of clients that can be supported is limited, in theory, only by the system resources available (and any constraints that might be imposed by the JDK version in use).

The interaction between an Echo client and the server is very simple; after the client establishes a connection, it sends one or more messages to the server, which in turn echoes each message to the client. While this may not seem terribly useful by itself, it exemplifies the request-response interaction that’s typical of client/server systems.

We’ll begin this project by examining the server-side code.

2.3. Writing the Echo server

All Netty servers require the following:

  • At least one ChannelHandler —This component implements the server’s processing of data received from the client—its business logic.
  • Bootstrapping —This is the startup code that configures the server. At a minimum, it binds the server to the port on which it will listen for connection requests.

In the remainder of this section we’ll describe the logic and bootstrapping code for the Echo server.

2.3.1. ChannelHandlers and business logic

In chapter 1 we introduced Futures and callbacks and illustrated their use in an event-driven design. We also discussed ChannelHandler, the parent of a family of interfaces whose implementations receive and react to event notifications. In Netty applications, all data-processing logic is contained in implementations of these core abstractions.

Because your Echo server will respond to incoming messages, it will need to implement interface ChannelInboundHandler, which defines methods for acting on inbound events. This simple application will require only a few of these methods, so it will be sufficient to subclass ChannelInboundHandlerAdapter, which provides a default implementation of ChannelInboundHandler.

The following methods interest us:

  • channelRead() —Called for each incoming message
  • channelReadComplete() —Notifies the handler that the last call made to channelRead() was the last message in the current batch
  • exceptionCaught() —Called if an exception is thrown during the read operation

The Echo server’s ChannelHandler implementation is EchoServerHandler, shown in the following listing.

Listing 2.1. EchoServerHandler

ChannelInboundHandlerAdapter has a straightforward API, and each of its methods can be overridden to hook into the event lifecycle at the appropriate point. Because you need to handle all received data, you override channelRead(). In this server you simply echo the data to the remote peer.

Overriding exceptionCaught() allows you to react to any Throwable subtypes—here you log the exception and close the connection. A more elaborate application might try to recover from the exception, but in this case simply closing the connection signals to the remote peer that an error has occurred.

What happens if an exception isn’t caught?

Every Channel has an associated ChannelPipeline, which holds a chain of ChannelHandler instances. By default, a handler will forward the invocation of a handler method to the next one in the chain. Therefore, if exceptionCaught() is not implemented somewhere along the chain, exceptions received will travel to the end of the ChannelPipeline and will be logged. For this reason, your application should supply at least one ChannelHandler that implements exceptionCaught(). (Section 6.4 discusses exception handling in detail.)

In addition to ChannelInboundHandlerAdapter, there are many ChannelHandler subtypes and implementations to learn about, and we’ll cover these in detail in chapters 6 and 7. For now, please keep these key points in mind:

  • ChannelHandlers are invoked for different types of events.
  • Applications implement or extend ChannelHandlers to hook into the event lifecycle and provide custom application logic.
  • Architecturally, ChannelHandlers help to keep your business logic decoupled from networking code. This simplifies development as the code evolves in response to changing requirements.

2.3.2. Bootstrapping the server

Having discussed the core business logic implemented by EchoServerHandler, we can now examine the bootstrapping of the server itself, which involves the following:

  • Bind to the port on which the server will listen for and accept incoming connection requests
  • Configure Channels to notify an EchoServerHandler instance about inbound messages
Transports

In this section you’ll encounter the term transport. In the standard, multilayered view of networking protocols, the transport layer is the one that provides services for end-to-end or host-to-host communications.

Internet communications are based on the TCP transport. NIO transport refers to a transport that’s mostly identical to TCP except for server-side performance enhancements provided by the Java NIO implementation.

Transports will be discussed in detail in chapter 4.

The following listing shows the complete code for the EchoServer class.

Listing 2.2. EchoServer class

In you create a ServerBootstrap instance. Because you’re using the NIO transport, you specify the NioEventLoopGroup to accept and handle new connections and the NioServerSocketChannel as the channel type. After this you set the local address to an InetSocketAddress with the selected port . The server will bind to this address to listen for new connection requests.

In you make use of a special class, ChannelInitializer. This is key. When a new connection is accepted, a new child Channel will be created, and the ChannelInitializer will add an instance of your EchoServerHandler to the Channel’s ChannelPipeline. As we explained earlier, this handler will receive notifications about inbound messages.

Although NIO is scalable, its proper configuration, especially as regards multithreading, is not trivial. Netty’s design encapsulates most of the complexity, and we’ll discuss the relevant abstractions (EventLoopGroup, SocketChannel, and ChannelInitializer) in more detail in chapter 3.

Next you bind the server and wait until the bind completes. (The call to sync() causes the current Thread to block until then.) At , the application will wait until the server’s Channel closes (because you call sync() on the Channel’s CloseFuture). You can then shut down the EventLoopGroup and release all resources, including all created threads .

NIO is used in this example because it’s currently the most widely used transport, thanks to its scalability and thoroughgoing asynchrony. But a different transport implementation could be used as well. If you wished to use the OIO transport in your server, you’d specify OioServerSocketChannel and OioEventLoopGroup. We’ll explore transports in greater detail in chapter 4.

In the meantime, let’s review the important steps in the server implementation you just completed. These are the primary code components of the server:

  • The EchoServerHandler implements the business logic.
  • The main() method bootstraps the server.

The following steps are required in bootstrapping:

  • Create a ServerBootstrap instance to bootstrap and bind the server.
  • Create and assign an NioEventLoopGroup instance to handle event processing, such as accepting new connections and reading/writing data.
  • Specify the local InetSocketAddress to which the server binds.
  • Initialize each new Channel with an EchoServerHandler instance.
  • Call ServerBootstrap.bind() to bind the server.

At this point the server is initialized and ready to be used. In the next section we’ll examine the code for the client application.

2.4. Writing an Echo client

The Echo client will

1.  Connect to the server

2.  Send one or more messages

3.  For each message, wait for and receive the same message back from the server

4.  Close the connection

Writing the client involves the same two main code areas you saw in the server: business logic and bootstrapping.

2.4.1. Implementing the client logic with ChannelHandlers

Like the server, the client will have a ChannelInboundHandler to process the data. In this case, you’ll extend the class SimpleChannelInboundHandler to handle all the needed tasks, as shown in listing 2.3. This requires overriding the following methods:

  • channelActive() —Called after the connection to the server is established
  • channelRead0() —Called when a message is received from the server
  • exceptionCaught() —Called if an exception is raised during processing
Listing 2.3. ChannelHandler for the client

First you override channelActive(), invoked when a connection has been established. This ensures that something is written to the server as soon as possible, which in this case is a byte buffer that encodes the string "Netty rocks!".

Next you override the method channelRead0(). This method is called whenever data is received. Note that the message sent by the server may be received in chunks. That is, if the server sends 5 bytes, there’s no guarantee that all 5 bytes will be received at once. Even for such a small amount of data, the channelRead0() method could be called twice, first with a ByteBuf (Netty’s byte container) holding 3 bytes, and second with a ByteBuf holding 2 bytes. As a stream-oriented protocol, TCP guarantees that the bytes will be received in the order in which they were sent by the server.

The third method you override is exceptionCaught(). Just as in EchoServerHandler (listing 2.2), Throwable is logged and the channel is closed, in this case terminating the connection to the server.

SimpleChannelInboundHandler vs. ChannelInboundHandler

You may be wondering why we used SimpleChannelInboundHandler in the client instead of the ChannelInboundHandlerAdapter used in the EchoServerHandler. This has to do with the interaction of two factors: how the business logic processes messages and how Netty manages resources.

In the client, when channelRead0() completes, you have the incoming message and you’re done with it. When the method returns, SimpleChannelInboundHandler takes care of releasing the memory reference to the ByteBuf that holds the message.

In EchoServerHandler you still have to echo the incoming message to the sender, and the write() operation, which is asynchronous, may not complete until after channelRead() returns (shown in listing 2.1). For this reason EchoServerHandler extends ChannelInboundHandlerAdapter, which doesn’t release the message at this point.

The message is released in channelReadComplete() in the EchoServerHandler when writeAndFlush() is called (listing 2.1).

Chapters 5 and 6 will cover message resource management in detail.

2.4.2. Bootstrapping the client

As you’ll see in the next listing, bootstrapping a client is similar to bootstrapping a server, with the difference that instead of binding to a listening port the client uses host and port parameters to connect to a remote address, here that of the Echo server.

Listing 2.4. Main class for the client

As before, the NIO transport is used. Note that you could use different transports in the client and server; for example, NIO transport on the server side and OIO transport on the client side. In chapter 4 we’ll examine the factors and scenarios that would lead you to select a specific transport for a specific use case.

Let’s review the important points introduced in this section:

  • A Bootstrap instance is created to initialize the client.
  • An NioEventLoopGroup instance is assigned to handle the event processing, which includes creating new connections and processing inbound and outbound data.
  • An InetSocketAddress is created for the connection to the server.
  • An EchoClientHandler will be installed in the pipeline when the connection is established.
  • After everything is set up, Bootstrap.connect() is called to connect to the remote peer.

Having finished the client, you can proceed to build the system and test it out.

2.5. Building and running the Echo server and client

In this section we’ll cover all the steps needed to compile and run the Echo server and client.

The Echo client/server Maven project

This book’s appendix uses the configuration of the Echo client/server project to explain in detail how multimodule Maven projects are organized. This isn’t required reading for building and running the applications, but it’s recommended for gaining a better understanding of the book’s examples and of the Netty project itself.

2.5.1. Running the build

To build the Echo client and server, go to the chapter2 directory under the code samples root directory and execute the following command:

mvn clean package

This should produce something very much like the output shown in listing 2.5 (we’ve edited out a few nonessential steps in the build).

Listing 2.5. Building the Echo client and server
[INFO] Scanning for projects...
[INFO] -------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] Chapter 2. Your First Netty Application - Echo App
[INFO] Chapter 2. Echo Client
[INFO] Chapter 2. Echo Server
[INFO]
[INFO] -------------------------------------------------------------------
[INFO] Building Chapter 2. Your First Netty Application - 2.0-SNAPSHOT
[INFO] -------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.6.1:clean (default-clean) @ chapter2 ---
[INFO]
[INFO] -------------------------------------------------------------------
[INFO] Building Chapter 2. Echo Client 2.0-SNAPSHOT
[INFO] -------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.6.1:clean (default-clean)
    @ echo-client ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources)
    @ echo-client ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile)
    @ echo-client ---

[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to
    
etty-in-actionchapter2Client	argetclasses
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources)
    @ echo-client ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory
    
etty-in-actionchapter2Clientsrc	est
esources
[INFO]
[INFO] --- maven-compiler-plugin:3.3:testCompile (default-testCompile)
    @ echo-client ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test)
    @ echo-client ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ echo-client ---
[INFO] Building jar:
    
etty-in-actionchapter2Client	argetecho-client-2.0-SNAPSHOT.jar
[INFO]
[INFO] -------------------------------------------------------------------
[INFO] Building Chapter 2. Echo Server 2.0-SNAPSHOT
[INFO] -------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.6.1:clean (default-clean)
    @ echo-server ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources)
    @ echo-server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile)
    @ echo-server ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to
    
etty-in-actionchapter2Server	argetclasses
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources)
    @ echo-server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory
    
etty-in-actionchapter2Serversrc	est
esources
[INFO]
[INFO] --- maven-compiler-plugin:3.3:testCompile (default-testCompile)
    @ echo-server ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test)
    @ echo-server ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ echo-server ---

[INFO] Building jar:
    
etty-in-actionchapter2Server	argetecho-server-2.0-SNAPSHOT.jar
[INFO] -------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Chapter 2. Your First Netty Application ... SUCCESS [  0.134 s]
[INFO] Chapter 2. Echo Client .................... SUCCESS [  1.509 s]
[INFO] Chapter 2. Echo Ser........................ SUCCESS [  0.139 s]
[INFO] -------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------------
[INFO] Total time: 1.886 s
[INFO] Finished at: 2015-11-18T17:14:10-05:00
[INFO] Final Memory: 18M/216M
[INFO] -------------------------------------------------------------------

Here are the main steps recorded in the preceding build log:

  • Maven determines the build order: first the parent pom.xml, and then the modules (subprojects).
  • If the Netty artifacts aren’t found in the user’s local repository, Maven will download them from the public Maven repositories (not shown here).
  • The clean and compile phases of the build lifecycle are run.
  • The maven-jar-plugin is executed.

The Maven Reactor Summary shows that all projects have been successfully built. A listing of the target directories in the two subprojects should now resemble the following listing.

Listing 2.6. Build artifacts
Directory of niachapter2Client	arget
03/16/2015  09:45 PM    <DIR>          classes
03/16/2015  09:45 PM             5,614 echo-client-1.0-SNAPSHOT.jar
03/16/2015  09:45 PM    <DIR>          generated-sources
03/16/2015  09:45 PM    <DIR>          maven-archiver
03/16/2015  09:45 PM    <DIR>          maven-status

Directory of niachapter2Server/target
03/16/2015  09:45 PM    <DIR>          classes
03/16/2015  09:45 PM             5,629 echo-server-1.0-SNAPSHOT.jar
03/16/2015  09:45 PM    <DIR>          generated-sources
03/16/2015  09:45 PM    <DIR>          maven-archiver
03/16/2015  09:45 PM    <DIR>          maven-status

2.5.2. Running the Echo server and client

To run the application components, you could use the Java command directly. But in the POM file, the exec-maven-plugin is configured to do this for you (see the appendix for details).

Open two console windows side by side, one logged into the chapter2Server directory and the other into chapter2Client.

In the server’s console, execute this command:

mvn exec:java

You should see something like the following:

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------------------------------------------------------
[INFO] Building Echo Server 1.0-SNAPSHOT
[INFO] ----------------------------------------------------------------------
[INFO]
[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) >
    validate @ echo-server >>>
[INFO]
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) <
    validate @ echo-server <<<
[INFO]
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ echo-server ---
    nia.chapter2.echoserver.EchoServer
    started and listening for connections on /0:0:0:0:0:0:0:0:9999

The server has been started and is ready to accept connections. Now execute the same command in the client’s console:

mvn exec:java

You should see the following:

[INFO] Scanning for projects...
[INFO]
[INFO] -------------------------------------------------------------------
[INFO] Building Echo Client 1.0-SNAPSHOT
[INFO] -------------------------------------------------------------------
[INFO]
[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) >
    validate @ echo-client >>>
[INFO]
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) <
    validate @ echo-client <<<
[INFO]
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ echo-client ---
    Client received: Netty rocks!
[INFO] -------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------------
[INFO] Total time: 2.833 s
[INFO] Finished at: 2015-03-16T22:03:54-04:00
[INFO] Final Memory: 10M/309M
[INFO] -------------------------------------------------------------------

And in the server console you should see this:

Server received: Netty rocks!

You’ll see this log statement in the server’s console every time you run the client.

Here’s what happens:

1.  As soon as the client is connected, it sends its message: Netty rocks!

2.  The server reports the received message and echoes it to the client.

3.  The client reports the returned message and exits.

What you’ve seen is the expected behavior; now let’s see how failures are handled. The server should still be running, so type Ctrl-C in the server console to stop the process. Once it has terminated, start the client again with

mvn exec:java

This shows the output you should see from the client when it’s unable to connect to the server.

Listing 2.7. Exception handling in the Echo client
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------------------------------------------------
[INFO] Building Echo Client 1.0-SNAPSHOT
[INFO] --------------------------------------------------------------------
[INFO]
[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) >
    validate @ echo-client >>>
[INFO]
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) <
    validate @ echo-client <<<
[INFO]
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ echo-client ---
[WARNING]
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    . . .
    Caused by: java.net.ConnectException: Connection refused:
    no further information: localhost/127.0.0.1:9999
        at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
        at sun.nio.ch.SocketChannelImpl
        .finishConnect(SocketChannelImpl.java:739)
        at io.netty.channel.socket.nio.NioSocketChannel
        .doFinishConnect(NioSocketChannel.java:208)
        at io.netty.channel.nio
        .AbstractNioChannel$AbstractNioUnsafe
        .finishConnect(AbstractNioChannel.java:281)
        at io.netty.channel.nio.NioEventLoop
        .processSelectedKey(NioEventLoop.java:528)
        at io.netty.channel.nio.NioEventLoop.
        processSelectedKeysOptimized(NioEventLoop.java:468)
        at io.netty.channel.nio.NioEventLoop
        .processSelectedKeys(NioEventLoop.java:382)
        at io.netty.channel.nio.NioEventLoop

        .run(NioEventLoop.java:354)
        at io.netty.util.concurrent.SingleThreadEventExecutor$2
        .run(SingleThreadEventExecutor.java:116)
        at io.netty.util.concurrent.DefaultThreadFactory
        $DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    . . .
[INFO] --------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] --------------------------------------------------------------------
[INFO] Total time: 3.801 s
[INFO] Finished at: 2015-03-16T22:11:16-04:00
[INFO] Final Memory: 10M/309M
[INFO] --------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:
    exec-maven-plugin:1.2.1:java (default-cli) on project echo-client:
        An exception occured while executing the Java class. null:
        InvocationTargetException: Connection refused:
        no further information: localhost/127.0.0.1:9999 -> [Help 1]

What happened? The client tried to connect to the server, which it expected to find running at localhost:9999. This failed (as expected) because the server had been stopped previously, causing a java.net.ConnectException in the client. This exception triggered the exceptionCaught()method of the EchoClientHandler, which prints out the stack trace and closes the channel (see listing 2.3.)

2.6. Summary

In this chapter you set up your development environment and built and ran your first Netty client and server. Although this is a simple application, it will scale to several thousand concurrent connections—many more messages per second than a plain vanilla socket-based Java application would be able to handle.

In the following chapters, you’ll see many more examples of how Netty simplifies scalability and concurrency. We’ll also go deeper into Netty’s support for the architectural principle of separation of concerns. By providing the right abstractions for decoupling business logic from networking logic, Netty makes it easy to keep pace with rapidly evolving requirements without jeopardizing system stability.

In the next chapter, we’ll provide an overview of Netty’s architecture. This will give you the context for the in-depth and comprehensive study of Netty’s internals that will follow in subsequent chapters.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset