├── .gitignore
├── LICENSE
├── README.md
├── TOC.md
├── chapter1
├── .gitignore
├── .project
├── README.md
├── build.gradle
└── src
│ └── main
│ └── java
│ ├── chapter1
│ ├── recipe1
│ │ ├── AsynchTcpServer.java
│ │ ├── TcpClient.java
│ │ ├── TcpClientLambdaHandler.java
│ │ └── TcpServerHandler.java
│ ├── recipe2
│ │ ├── TcpClient.java
│ │ └── TcpClientHandler.java
│ ├── recipe3
│ │ ├── TcpClient.java
│ │ ├── TcpClientHandler.java
│ │ ├── TcpServer.java
│ │ └── TcpServerHandler.java
│ ├── recipe4
│ │ ├── TcpClientHandler.java
│ │ ├── TcpClientPipe.java
│ │ ├── TcpServerInboundHandler.java
│ │ ├── TcpServerOutboundHandler.java
│ │ └── TcpServerPipe.java
│ └── recipe6
│ │ ├── DataPipelineProcessingServer.java
│ │ └── DataProcessingPipeline.java
│ ├── log4j.properties
│ └── netty
│ └── cookbook
│ └── common
│ ├── BootstrapTemplate.java
│ ├── CallbackProcessor.java
│ ├── CharPool.java
│ ├── FileUtils.java
│ ├── LogUtil.java
│ ├── StringPool.java
│ ├── StringUtil.java
│ ├── TcpChannelHandler.java
│ └── UrlUtil.java
├── chapter2
├── .gitignore
├── .project
├── README.md
├── build.gradle
├── data
│ └── text-file.txt
├── lib
│ └── netty-codec-ftp-0.2-SNAPSHOT.jar
├── src
│ └── main
│ │ ├── avro
│ │ └── mail.avpr
│ │ └── java
│ │ ├── avro
│ │ ├── Mail.java
│ │ └── Message.java
│ │ ├── chapter2
│ │ ├── recipe10
│ │ │ ├── ClientAvroRPC.java
│ │ │ └── ProxyServerAvroRPC.java
│ │ ├── recipe11
│ │ │ └── HttpDownloader.java
│ │ ├── recipe2
│ │ │ ├── Receiver.java
│ │ │ └── Sender.java
│ │ ├── recipe3
│ │ │ ├── PurchaseClient.java
│ │ │ ├── PurchaseClientHandler.java
│ │ │ ├── PurchaseData.java
│ │ │ ├── PurchaseDataDecoder.java
│ │ │ ├── PurchaseDataEncoder.java
│ │ │ └── PurchaseServer.java
│ │ ├── recipe4
│ │ │ └── MultiSocketServer.java
│ │ ├── recipe6
│ │ │ └── NettyMonitorIO.java
│ │ ├── recipe7
│ │ │ ├── HeartBeatHandler.java
│ │ │ ├── ImportantServer.java
│ │ │ └── ServerHealthChecker.java
│ │ ├── recipe8
│ │ │ ├── SimpleSctpClient.java
│ │ │ ├── SimpleSctpClientHandler.java
│ │ │ ├── SimpleSctpServer.java
│ │ │ └── SimpleSctpServerHandler.java
│ │ └── recipe9
│ │ │ ├── FileReceiver.java
│ │ │ └── SimpleServerFTP.java
│ │ ├── log4j.properties
│ │ └── netty
│ │ └── cookbook
│ │ └── common
│ │ ├── BootstrapTemplate.java
│ │ ├── CallbackProcessor.java
│ │ ├── CharPool.java
│ │ ├── FileUtils.java
│ │ ├── LogUtil.java
│ │ ├── StringPool.java
│ │ ├── StringUtil.java
│ │ ├── TcpChannelHandler.java
│ │ └── UrlUtil.java
└── tools
│ └── avro-tools-1.7.7.jar
├── chapter3
├── .gitignore
├── .project
├── README.md
├── build.gradle
├── configs
│ ├── redis-connection-pool-configs.json
│ └── regexes.yaml
├── lib
│ ├── DateAdapterJ-1.1.3-20141216.175259-8.jar
│ ├── RestExpress-0.11.0-20150113.201733-1.jar
│ ├── RestExpress-Common-0.11.0-20150113.201714-1.jar
│ └── alpn-boot-8.1.0.v20141016.jar
└── src
│ └── main
│ ├── java
│ ├── chapter3
│ │ ├── recipe1
│ │ │ ├── HttpEventRoutingHandler.java
│ │ │ ├── HttpServerWithRouter.java
│ │ │ └── UriMatcher.java
│ │ ├── recipe2
│ │ │ ├── DispatcherServletChannelInitializer.java
│ │ │ ├── HelloController.java
│ │ │ ├── HttpServerSpringMVC.java
│ │ │ ├── ServletNettyChannelHandler.java
│ │ │ ├── TemplateConfiguration.java
│ │ │ └── WebConfig.java
│ │ ├── recipe3
│ │ │ ├── HttpFileServer.java
│ │ │ └── HttpStaticFileServerHandler.java
│ │ ├── recipe4
│ │ │ ├── NettyHttpServerWithCORS.java
│ │ │ └── SimpleCORSHandler.java
│ │ ├── recipe5
│ │ │ ├── HttpServerSPDY.java
│ │ │ ├── SpdyOrHttpHandler.java
│ │ │ └── SpdyServerHandler.java
│ │ └── recipe6
│ │ │ ├── FunctionPipeline.java
│ │ │ ├── FunctionsChannelHandler.java
│ │ │ ├── LambdaHttpServer.java
│ │ │ ├── SimpleHttpRequest.java
│ │ │ ├── SimpleHttpResponse.java
│ │ │ └── functions
│ │ │ ├── Decorator.java
│ │ │ ├── Filter.java
│ │ │ ├── FinalProcessor.java
│ │ │ └── Processor.java
│ ├── log4j.properties
│ ├── netty
│ │ └── cookbook
│ │ │ └── common
│ │ │ ├── CallbackActor.java
│ │ │ ├── CallbackProcessor.java
│ │ │ ├── CharPool.java
│ │ │ ├── FileUtils.java
│ │ │ ├── JsOptimizerUtil.java
│ │ │ ├── LogUtil.java
│ │ │ ├── NashornEngineUtil.java
│ │ │ ├── NettyServerUtil.java
│ │ │ ├── StringPool.java
│ │ │ ├── StringUtil.java
│ │ │ ├── TcpChannelHandler.java
│ │ │ ├── UrlUtil.java
│ │ │ ├── http
│ │ │ ├── BasicHttpResponseHandler.java
│ │ │ ├── ContentTypePool.java
│ │ │ ├── HttpEventHandler.java
│ │ │ ├── HttpEventProcessor.java
│ │ │ ├── HttpOutputResource.java
│ │ │ ├── HttpRequestData.java
│ │ │ ├── HttpRequestEvent.java
│ │ │ └── NettyHttpUtil.java
│ │ │ └── redis
│ │ │ ├── RedisCommand.java
│ │ │ ├── RedisConnectionPoolConfig.java
│ │ │ └── RedisInfo.java
│ └── rfx
│ │ └── server
│ │ └── util
│ │ └── ua
│ │ ├── Client.java
│ │ ├── Device.java
│ │ ├── DeviceParser.java
│ │ ├── OS.java
│ │ ├── OSParser.java
│ │ ├── Parser.java
│ │ ├── UserAgent.java
│ │ └── UserAgentParser.java
│ └── resources
│ └── templates
│ ├── cors.html
│ ├── hello-view.html
│ └── js
│ └── script.js
├── chapter4
├── .gitignore
├── .project
├── README.md
├── build.gradle
├── configs
│ ├── redis-connection-pool-configs.json
│ └── regexes.yaml
└── src
│ └── main
│ └── java
│ ├── chapter4
│ ├── recipe1
│ │ └── WebSocketServer.java
│ ├── recipe2
│ │ └── RealtimeWebSocketIO.java
│ ├── recipe3
│ │ └── ChatServerWithSTOMP.java
│ └── recipe4
│ │ ├── NettyRxJavaServer.java
│ │ └── RealtimeWidgetServer.java
│ ├── log4j.properties
│ ├── netty
│ └── cookbook
│ │ └── common
│ │ ├── BootstrapTemplate.java
│ │ ├── CallbackProcessor.java
│ │ ├── CharPool.java
│ │ ├── FileUtils.java
│ │ ├── LogUtil.java
│ │ ├── StringPool.java
│ │ ├── StringUtil.java
│ │ ├── TcpChannelHandler.java
│ │ ├── UrlUtil.java
│ │ ├── http
│ │ ├── ContentTypePool.java
│ │ ├── HttpOutputResource.java
│ │ ├── HttpRequestData.java
│ │ ├── HttpRequestEvent.java
│ │ └── NettyHttpUtil.java
│ │ └── redis
│ │ ├── RedisCommand.java
│ │ ├── RedisConnectionPoolConfig.java
│ │ └── RedisInfo.java
│ └── rfx
│ └── server
│ └── util
│ └── ua
│ ├── Client.java
│ ├── Device.java
│ ├── DeviceParser.java
│ ├── OS.java
│ ├── OSParser.java
│ ├── Parser.java
│ ├── UserAgent.java
│ └── UserAgentParser.java
├── chapter5
├── .gitignore
├── .project
├── README.md
├── build.gradle
└── src
│ └── main
│ └── java
│ ├── chapter4
│ ├── recipe1
│ │ └── WebSocketServer.java
│ ├── recipe2
│ │ └── RealtimeWebSocketIO.java
│ ├── recipe3
│ │ └── ChatServerWithSTOMP.java
│ └── recipe4
│ │ └── RealtimeWidgetServer.java
│ ├── log4j.properties
│ ├── netty
│ └── cookbook
│ │ └── common
│ │ ├── BootstrapTemplate.java
│ │ ├── CallbackProcessor.java
│ │ ├── CharPool.java
│ │ ├── FileUtils.java
│ │ ├── LogUtil.java
│ │ ├── StringPool.java
│ │ ├── StringUtil.java
│ │ ├── TcpChannelHandler.java
│ │ ├── UrlUtil.java
│ │ ├── http
│ │ ├── ContentTypePool.java
│ │ ├── HttpOutputResource.java
│ │ ├── HttpRequestData.java
│ │ ├── HttpRequestEvent.java
│ │ └── NettyHttpUtil.java
│ │ └── redis
│ │ ├── RedisCommand.java
│ │ ├── RedisConnectionPoolConfig.java
│ │ └── RedisInfo.java
│ └── rfx
│ └── server
│ └── util
│ └── ua
│ ├── Client.java
│ ├── Device.java
│ ├── DeviceParser.java
│ ├── OS.java
│ ├── OSParser.java
│ ├── Parser.java
│ ├── UserAgent.java
│ └── UserAgentParser.java
├── chapter6
├── .gitignore
├── .project
├── README.md
├── build.gradle
└── src
│ └── main
│ └── java
│ ├── chapter4
│ ├── recipe1
│ │ └── WebSocketServer.java
│ ├── recipe2
│ │ └── RealtimeWebSocketIO.java
│ ├── recipe3
│ │ └── ChatServerWithSTOMP.java
│ └── recipe4
│ │ └── RealtimeWidgetServer.java
│ ├── log4j.properties
│ ├── netty
│ └── cookbook
│ │ └── common
│ │ ├── BootstrapTemplate.java
│ │ ├── CallbackProcessor.java
│ │ ├── CharPool.java
│ │ ├── FileUtils.java
│ │ ├── LogUtil.java
│ │ ├── StringPool.java
│ │ ├── StringUtil.java
│ │ ├── TcpChannelHandler.java
│ │ ├── UrlUtil.java
│ │ ├── http
│ │ ├── ContentTypePool.java
│ │ ├── HttpOutputResource.java
│ │ ├── HttpRequestData.java
│ │ ├── HttpRequestEvent.java
│ │ └── NettyHttpUtil.java
│ │ └── redis
│ │ ├── RedisCommand.java
│ │ ├── RedisConnectionPoolConfig.java
│ │ └── RedisInfo.java
│ └── rfx
│ └── server
│ └── util
│ └── ua
│ ├── Client.java
│ ├── Device.java
│ ├── DeviceParser.java
│ ├── OS.java
│ ├── OSParser.java
│ ├── Parser.java
│ ├── UserAgent.java
│ └── UserAgentParser.java
├── chapter7
├── .gitignore
├── .project
├── README.md
├── build.gradle
└── src
│ └── main
│ └── java
│ ├── chapter7
│ └── recipe1
│ │ ├── client
│ │ ├── Http2Client.java
│ │ ├── Http2ClientInitializer.java
│ │ ├── Http2SettingsHandler.java
│ │ └── HttpResponseHandler.java
│ │ └── server
│ │ ├── HelloWorldHttp1Handler.java
│ │ ├── HelloWorldHttp2Handler.java
│ │ ├── Http2OrHttpHandler.java
│ │ ├── Http2Server.java
│ │ └── Http2ServerInitializer.java
│ ├── log4j.properties
│ ├── netty
│ └── cookbook
│ │ └── common
│ │ ├── BootstrapTemplate.java
│ │ ├── CallbackProcessor.java
│ │ ├── CharPool.java
│ │ ├── FileUtils.java
│ │ ├── Http2Util.java
│ │ ├── LogUtil.java
│ │ ├── StringPool.java
│ │ ├── StringUtil.java
│ │ ├── UrlUtil.java
│ │ └── redis
│ │ ├── RedisCommand.java
│ │ ├── RedisConnectionPoolConfig.java
│ │ └── RedisInfo.java
│ └── rfx
│ └── server
│ └── util
│ └── ua
│ ├── Client.java
│ ├── Device.java
│ ├── DeviceParser.java
│ ├── OS.java
│ ├── OSParser.java
│ ├── Parser.java
│ ├── UserAgent.java
│ └── UserAgentParser.java
├── chapter8
├── .gitignore
├── .project
├── README.md
├── build.gradle
└── src
│ └── main
│ └── java
│ ├── chapter4
│ ├── recipe1
│ │ └── WebSocketServer.java
│ ├── recipe2
│ │ └── RealtimeWebSocketIO.java
│ ├── recipe3
│ │ └── ChatServerWithSTOMP.java
│ └── recipe4
│ │ └── RealtimeWidgetServer.java
│ ├── log4j.properties
│ ├── netty
│ └── cookbook
│ │ └── common
│ │ ├── BootstrapTemplate.java
│ │ ├── CallbackProcessor.java
│ │ ├── CharPool.java
│ │ ├── FileUtils.java
│ │ ├── LogUtil.java
│ │ ├── StringPool.java
│ │ ├── StringUtil.java
│ │ ├── TcpChannelHandler.java
│ │ ├── UrlUtil.java
│ │ ├── http
│ │ ├── ContentTypePool.java
│ │ ├── HttpOutputResource.java
│ │ ├── HttpRequestData.java
│ │ ├── HttpRequestEvent.java
│ │ └── NettyHttpUtil.java
│ │ └── redis
│ │ ├── RedisCommand.java
│ │ ├── RedisConnectionPoolConfig.java
│ │ └── RedisInfo.java
│ └── rfx
│ └── server
│ └── util
│ └── ua
│ ├── Client.java
│ ├── Device.java
│ ├── DeviceParser.java
│ ├── OS.java
│ ├── OSParser.java
│ ├── Parser.java
│ ├── UserAgent.java
│ └── UserAgentParser.java
├── chapter9
├── .gitignore
├── .project
├── README.md
├── build.gradle
└── src
│ └── main
│ └── java
│ ├── chapter4
│ ├── recipe1
│ │ └── WebSocketServer.java
│ ├── recipe2
│ │ └── RealtimeWebSocketIO.java
│ ├── recipe3
│ │ └── ChatServerWithSTOMP.java
│ └── recipe4
│ │ └── RealtimeWidgetServer.java
│ ├── log4j.properties
│ ├── netty
│ └── cookbook
│ │ └── common
│ │ ├── BootstrapTemplate.java
│ │ ├── CallbackProcessor.java
│ │ ├── CharPool.java
│ │ ├── FileUtils.java
│ │ ├── LogUtil.java
│ │ ├── StringPool.java
│ │ ├── StringUtil.java
│ │ ├── TcpChannelHandler.java
│ │ ├── UrlUtil.java
│ │ ├── http
│ │ ├── ContentTypePool.java
│ │ ├── HttpOutputResource.java
│ │ ├── HttpRequestData.java
│ │ ├── HttpRequestEvent.java
│ │ └── NettyHttpUtil.java
│ │ └── redis
│ │ ├── RedisCommand.java
│ │ ├── RedisConnectionPoolConfig.java
│ │ └── RedisInfo.java
│ └── rfx
│ └── server
│ └── util
│ └── ua
│ ├── Client.java
│ ├── Device.java
│ ├── DeviceParser.java
│ ├── OS.java
│ ├── OSParser.java
│ ├── Parser.java
│ ├── UserAgent.java
│ └── UserAgentParser.java
└── netty-cookbook-java-src
├── .gitignore
├── .project
├── README.txt
├── build.gradle
├── configs
├── redis-connection-pool-configs.json
└── regexes.yaml
├── data
├── text-file.txt
└── www.mc2ads.com.html
├── lib
├── mongodb-async-driver-2.0.1.jar
└── netty-codec-ftp-0.2-SNAPSHOT.jar
├── src
├── main
│ ├── avro
│ │ └── mail.avpr
│ └── java
│ │ ├── avro
│ │ ├── Mail.java
│ │ └── Message.java
│ │ ├── log4j.properties
│ │ ├── netty
│ │ └── cookbook
│ │ │ ├── chapter1
│ │ │ ├── recipe1
│ │ │ │ ├── AsynchTcpServer.java
│ │ │ │ ├── TcpClient.java
│ │ │ │ ├── TcpClientLambdaHandler.java
│ │ │ │ └── TcpServerHandler.java
│ │ │ ├── recipe2
│ │ │ │ ├── TcpClient.java
│ │ │ │ └── TcpClientHandler.java
│ │ │ ├── recipe3
│ │ │ │ ├── TcpClient.java
│ │ │ │ ├── TcpClientHandler.java
│ │ │ │ ├── TcpServer.java
│ │ │ │ └── TcpServerHandler.java
│ │ │ ├── recipe4
│ │ │ │ ├── TcpClientHandler.java
│ │ │ │ ├── TcpClientPipe.java
│ │ │ │ ├── TcpServerInboundHandler.java
│ │ │ │ ├── TcpServerOutboundHandler.java
│ │ │ │ └── TcpServerPipe.java
│ │ │ └── recipe6
│ │ │ │ ├── DataPipelineProcessingServer.java
│ │ │ │ └── DataProcessingPipeline.java
│ │ │ ├── chapter2
│ │ │ ├── recipe10
│ │ │ │ ├── ClientAvroRPC.java
│ │ │ │ └── ProxyServerAvroRPC.java
│ │ │ ├── recipe11
│ │ │ │ └── HttpDownloader.java
│ │ │ ├── recipe2
│ │ │ │ ├── Receiver.java
│ │ │ │ └── Sender.java
│ │ │ ├── recipe3
│ │ │ │ ├── PurchaseClient.java
│ │ │ │ ├── PurchaseClientHandler.java
│ │ │ │ ├── PurchaseDataDecoder.java
│ │ │ │ ├── PurchaseDataEncoder.java
│ │ │ │ └── PurchaseServer.java
│ │ │ ├── recipe4
│ │ │ │ └── MultiSocketServer.java
│ │ │ ├── recipe6
│ │ │ │ └── NettyMonitorIO.java
│ │ │ ├── recipe7
│ │ │ │ ├── HeartBeatHandler.java
│ │ │ │ ├── ImportantServer.java
│ │ │ │ └── ServerHealthChecker.java
│ │ │ ├── recipe8
│ │ │ │ ├── SimpleSctpClient.java
│ │ │ │ ├── SimpleSctpClientHandler.java
│ │ │ │ ├── SimpleSctpServer.java
│ │ │ │ └── SimpleSctpServerHandler.java
│ │ │ └── recipe9
│ │ │ │ ├── FileReceiver.java
│ │ │ │ └── SimpleServerFTP.java
│ │ │ ├── chapter3
│ │ │ └── recipe1
│ │ │ │ └── Echo.java
│ │ │ ├── chapter4
│ │ │ └── recipe5
│ │ │ │ ├── PubSubDemo.java
│ │ │ │ ├── SocialAnalyticUpdater.java
│ │ │ │ └── WebUrl.java
│ │ │ ├── chapter8
│ │ │ └── recipe3
│ │ │ │ ├── HttpEventProcessingHandler.java
│ │ │ │ ├── HttpServer.java
│ │ │ │ └── PublicHttpServerInitializer.java
│ │ │ └── common
│ │ │ ├── BootstrapTemplate.java
│ │ │ ├── CallbackActor.java
│ │ │ ├── CallbackProcessor.java
│ │ │ ├── CharPool.java
│ │ │ ├── FileUtils.java
│ │ │ ├── LogUtil.java
│ │ │ ├── StringPool.java
│ │ │ ├── StringUtil.java
│ │ │ ├── TcpChannelHandler.java
│ │ │ ├── UrlUtil.java
│ │ │ ├── http
│ │ │ ├── ContentTypePool.java
│ │ │ ├── HttpOutputResource.java
│ │ │ ├── HttpRequestData.java
│ │ │ ├── HttpRequestEvent.java
│ │ │ └── NettyHttpUtil.java
│ │ │ ├── model
│ │ │ └── PurchaseData.java
│ │ │ ├── redis
│ │ │ ├── RedisCommand.java
│ │ │ ├── RedisConnectionPoolConfig.java
│ │ │ └── RedisInfo.java
│ │ │ └── tcp
│ │ │ └── SimpleTcpServer.java
│ │ └── rfx
│ │ └── server
│ │ └── util
│ │ └── ua
│ │ ├── Client.java
│ │ ├── Device.java
│ │ ├── DeviceParser.java
│ │ ├── OS.java
│ │ ├── OSParser.java
│ │ ├── Parser.java
│ │ ├── UserAgent.java
│ │ └── UserAgentParser.java
└── test
│ └── java
│ └── classic
│ └── tcp
│ ├── TCPClient.java
│ └── TCPServer.java
└── tools
└── avro-tools-1.7.7.jar
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.war
8 | *.ear
9 |
10 | # ignore the gradle metadata and build folder
11 | **/bin/
12 | **/build/
13 | **/build/
14 | **/.gradle/
15 | **/.settings/
16 | *.classpath
17 |
18 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
19 | hs_err_pid*
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Netty Cookbook
2 |
3 | Download pdf at this link
4 | https://tantrieuf31.blogspot.com/2019/04/netty-cookbook.html
5 |
6 | ## Book Source Code
7 |
8 | The MIT License (MIT)
9 | Copyright (c) 2015 Trieu Nguyen
10 |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16 |
--------------------------------------------------------------------------------
/chapter1/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter1/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | NettyCookbook-chapter1
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter1/README.md:
--------------------------------------------------------------------------------
1 | Netty Cookbook - chapter 1 code
--------------------------------------------------------------------------------
/chapter1/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 |
4 | sourceCompatibility = 1.8
5 |
6 | version = '1.0'
7 |
8 | repositories {
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | compile (
14 | // common
15 | 'io.netty:netty-all:4.0.25.Final'
16 | ,'commons-io:commons-io:2.4'
17 | ,'org.apache.commons:commons-lang3:3.3.2'
18 | ,'log4j:log4j:1.2.17'
19 | ,'org.slf4j:slf4j-log4j12:1.7.7'
20 |
21 | ,'com.google.code.gson:gson:2.3'
22 | ,'com.google.guava:guava:18.0'
23 |
24 | )
25 | testCompile group: 'junit', name: 'junit', version: '4.11'
26 | }
--------------------------------------------------------------------------------
/chapter1/src/main/java/chapter1/recipe4/TcpServerInboundHandler.java:
--------------------------------------------------------------------------------
1 | package chapter1.recipe4;
2 |
3 | import io.netty.channel.ChannelHandler.Sharable;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 | import io.netty.util.ReferenceCountUtil;
7 |
8 | /**
9 | * Handler implementation for the TCP server.
10 | */
11 | @Sharable
12 | public class TcpServerInboundHandler extends ChannelInboundHandlerAdapter {
13 |
14 |
15 | @Override
16 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
17 | try {
18 | System.out.println("TcpServerInboundHandler");
19 | StringBuilder s = new StringBuilder();
20 | s.append("Ok TCP client, TcpServerInboundHandler got your message \"").append(msg).append("\"");
21 | ctx.write(s);
22 | } finally {
23 | ReferenceCountUtil.release(msg);
24 | }
25 | }
26 |
27 | @Override
28 | public void channelReadComplete(ChannelHandlerContext ctx) {
29 | ctx.flush();
30 | }
31 |
32 | @Override
33 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
34 | // Close the connection when an exception is raised.
35 | cause.printStackTrace();
36 | ctx.close();
37 | }
38 | }
--------------------------------------------------------------------------------
/chapter1/src/main/java/chapter1/recipe4/TcpServerOutboundHandler.java:
--------------------------------------------------------------------------------
1 | package chapter1.recipe4;
2 |
3 | import io.netty.channel.ChannelHandler.Sharable;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelOutboundHandlerAdapter;
6 | import io.netty.util.concurrent.Future;
7 | import io.netty.util.concurrent.GenericFutureListener;
8 |
9 | /**
10 | * Handler implementation for the TCP server.
11 | */
12 | @Sharable
13 | public class TcpServerOutboundHandler extends ChannelOutboundHandlerAdapter {
14 | @Override
15 | public void flush(ChannelHandlerContext ctx) throws Exception {
16 | super.flush(ctx);
17 | ctx.close().addListener(new GenericFutureListener>() {
18 | @Override
19 | public void operationComplete(Future super Void> future)
20 | throws Exception {
21 | System.out.println("close connection: "+future.isSuccess());
22 | }
23 | });
24 | }
25 |
26 | @Override
27 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
28 | // Close the connection when an exception is raised.
29 | cause.printStackTrace();
30 | ctx.close();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/chapter1/src/main/java/chapter1/recipe6/DataPipelineProcessingServer.java:
--------------------------------------------------------------------------------
1 | package chapter1.recipe6;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.Channel;
5 | import io.netty.channel.ChannelFuture;
6 | import io.netty.channel.ChannelOption;
7 | import io.netty.channel.EventLoopGroup;
8 | import io.netty.channel.nio.NioEventLoopGroup;
9 | import io.netty.channel.socket.nio.NioServerSocketChannel;
10 | import io.netty.handler.logging.LogLevel;
11 | import io.netty.handler.logging.LoggingHandler;
12 |
13 | public class DataPipelineProcessingServer {
14 | static final int PORT = 8007;
15 |
16 | public static void main(String[] args) throws Exception{
17 | // Configure the server.
18 | EventLoopGroup bossGroup = new NioEventLoopGroup(1);
19 | EventLoopGroup workerGroup = new NioEventLoopGroup();
20 | try {
21 | ServerBootstrap b = new ServerBootstrap();
22 | b.group(bossGroup, workerGroup)
23 | .channel(NioServerSocketChannel.class)
24 | .option(ChannelOption.SO_BACKLOG, 100)
25 | .handler(new LoggingHandler(LogLevel.INFO))
26 | .childHandler(new DataProcessingPipeline());
27 |
28 | // Start the server.
29 | ChannelFuture f = b.bind(PORT).sync();
30 | Channel channel = f.channel();
31 |
32 | // Wait until the server socket is closed.
33 | channel.closeFuture().sync();
34 | } finally {
35 | // Shut down all event loops to terminate all threads.
36 | bossGroup.shutdownGracefully();
37 | workerGroup.shutdownGracefully();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/chapter1/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter1/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter1/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter1/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter1/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/chapter1/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter2/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter2/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | NettyCookbook-chapter2
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter2/README.md:
--------------------------------------------------------------------------------
1 | Netty Cookbook - chapter 2 code
--------------------------------------------------------------------------------
/chapter2/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 |
4 | sourceCompatibility = 1.8
5 |
6 | version = '1.0'
7 |
8 | repositories {
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | compile (
14 | // common
15 | 'io.netty:netty-all:4.0.25.Final'
16 | ,'commons-io:commons-io:2.4'
17 | ,'org.apache.commons:commons-lang3:3.3.2'
18 | ,'log4j:log4j:1.2.17'
19 | ,'org.slf4j:slf4j-log4j12:1.7.7'
20 | ,'com.jcraft:jzlib:1.1.3'
21 | ,'org.yaml:snakeyaml:1.14'
22 |
23 | ,'com.google.code.gson:gson:2.3'
24 | ,'com.google.guava:guava:18.0'
25 | ,'com.typesafe.akka:akka-actor_2.11:2.3.6'
26 | ,'io.reactivex:rxjava:1.0.1'
27 | ,'redis.clients:jedis:2.6.1'
28 |
29 | ,'org.apache.avro:avro:1.7.7'
30 | ,'org.apache.avro:avro-ipc:1.7.7'
31 |
32 |
33 |
34 | , fileTree(dir: 'lib', include: '**/*.jar')
35 | )
36 | testCompile group: 'junit', name: 'junit', version: '4.11'
37 | }
--------------------------------------------------------------------------------
/chapter2/data/text-file.txt:
--------------------------------------------------------------------------------
1 | This is a message in text-file.txt
--------------------------------------------------------------------------------
/chapter2/lib/netty-codec-ftp-0.2-SNAPSHOT.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/chapter2/lib/netty-codec-ftp-0.2-SNAPSHOT.jar
--------------------------------------------------------------------------------
/chapter2/src/main/avro/mail.avpr:
--------------------------------------------------------------------------------
1 | {"namespace": "avro",
2 | "protocol": "Mail",
3 |
4 | "types": [
5 | {"name": "Message", "type": "record",
6 | "fields": [
7 | {"name": "to", "type": "string"},
8 | {"name": "from", "type": "string"},
9 | {"name": "body", "type": "string"}
10 | ]
11 | }
12 | ],
13 |
14 | "messages": {
15 | "send": {
16 | "request": [{"name": "message", "type": "Message"}],
17 | "response": "string"
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/chapter2/src/main/java/avro/Mail.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Autogenerated by Avro
3 | *
4 | * DO NOT EDIT DIRECTLY
5 | */
6 | package avro;
7 |
8 | @SuppressWarnings("all")
9 | @org.apache.avro.specific.AvroGenerated
10 | public interface Mail {
11 | public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"Mail\",\"namespace\":\"avro\",\"types\":[{\"type\":\"record\",\"name\":\"Message\",\"fields\":[{\"name\":\"to\",\"type\":\"string\"},{\"name\":\"from\",\"type\":\"string\"},{\"name\":\"body\",\"type\":\"string\"}]}],\"messages\":{\"send\":{\"request\":[{\"name\":\"message\",\"type\":\"Message\"}],\"response\":\"string\"}}}");
12 | java.lang.CharSequence send(avro.Message message) throws org.apache.avro.AvroRemoteException;
13 |
14 | @SuppressWarnings("all")
15 | public interface Callback extends Mail {
16 | public static final org.apache.avro.Protocol PROTOCOL = avro.Mail.PROTOCOL;
17 | void send(avro.Message message, org.apache.avro.ipc.Callback callback) throws java.io.IOException;
18 | }
19 | }
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe10/ClientAvroRPC.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe10;
2 |
3 |
4 | import java.io.IOException;
5 | import java.net.InetSocketAddress;
6 |
7 | import netty.cookbook.common.LogUtil;
8 |
9 | import org.apache.avro.ipc.NettyTransceiver;
10 | import org.apache.avro.ipc.specific.SpecificRequestor;
11 | import org.apache.avro.util.Utf8;
12 |
13 | import avro.Mail;
14 | import avro.Message;
15 |
16 | /**
17 | * Start ClientAvroRPC, and send a message.
18 | */
19 | public class ClientAvroRPC {
20 | public static void main(String[] args) throws IOException {
21 | if(args.length < 3){
22 | args = new String[] {"someone@example.com","myself@example.com","Hello !"};
23 | }
24 | NettyTransceiver client = new NettyTransceiver(new InetSocketAddress(10000));
25 | Mail proxy = (Mail) SpecificRequestor.getClient(Mail.class, client);
26 | LogUtil.println("ClientAvroRPC built OK, got proxy, ready to send data ...");
27 | Message message = new Message();
28 | message.setTo(new Utf8(args[0]));
29 | message.setFrom(new Utf8(args[1]));
30 | message.setBody(new Utf8(args[2]));
31 | LogUtil.println("Calling proxy.send with message: " + message.toString());
32 | LogUtil.println("Result from server: " + proxy.send(message));
33 | client.close();
34 | }
35 | }
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe10/ProxyServerAvroRPC.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe10;
2 |
3 | import java.io.IOException;
4 | import java.net.InetSocketAddress;
5 |
6 | import netty.cookbook.common.LogUtil;
7 |
8 | import org.apache.avro.ipc.NettyServer;
9 | import org.apache.avro.ipc.Server;
10 | import org.apache.avro.ipc.specific.SpecificResponder;
11 | import org.apache.avro.util.Utf8;
12 |
13 | import avro.Mail;
14 | import avro.Message;
15 |
16 | /**
17 | * @author trieu
18 | *
19 | */
20 | public class ProxyServerAvroRPC {
21 | public static class MailImpl implements Mail {
22 | public Utf8 send(Message message) {
23 | String s = String.format("message details, to:%s from:%s body:%s", message.getTo(), message.getFrom(), message.getBody());
24 | LogUtil.println(s);
25 | return new Utf8("Sent OK to "+ message.getTo());
26 | }
27 | }
28 | private static Server server;
29 | static void startServer() throws IOException {
30 | server = new NettyServer(new SpecificResponder(Mail.class,new MailImpl()), new InetSocketAddress(10000));
31 | }
32 | public static void main(String[] args) throws Exception {
33 | LogUtil.println("Starting ServerAvroRPC");
34 | startServer();
35 | LogUtil.println("ServerAvroRPC started and wait for 15s");
36 | Thread.sleep(15000);
37 | server.close();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe2/Receiver.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe2;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.socket.SocketChannel;
8 | import io.netty.handler.codec.string.StringDecoder;
9 | import io.netty.handler.codec.string.StringEncoder;
10 | import netty.cookbook.common.BootstrapTemplate;
11 |
12 | public class Receiver {
13 | static final int PORT = 8007;
14 | static final String HOST = "127.0.0.1";
15 | public static void main(String[] args) throws Exception {
16 | ChannelInitializer initializer = new ChannelInitializer() {
17 | @Override
18 | public void initChannel(SocketChannel ch) throws Exception {
19 | ChannelPipeline p = ch.pipeline();
20 | p.addLast(new StringEncoder());
21 | p.addLast(new StringDecoder());
22 | p.addLast(new ChannelInboundHandlerAdapter() {
23 | @Override
24 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
25 | System.out.println(msg);
26 | ctx.close();
27 | }
28 | });
29 | }
30 | };
31 | BootstrapTemplate.newServerBootstrap(HOST, PORT, initializer);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe2/Sender.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe2;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.socket.SocketChannel;
8 | import io.netty.handler.codec.string.StringDecoder;
9 | import io.netty.handler.codec.string.StringEncoder;
10 | import netty.cookbook.common.BootstrapTemplate;
11 |
12 | public class Sender {
13 | static final int PORT = 8007;
14 | static final String HOST = "127.0.0.1";
15 |
16 | public static void main(String[] args) throws InterruptedException {
17 | final String msg = "This is a long message";
18 | ChannelInitializer initializer = new ChannelInitializer() {
19 | @Override
20 | public void initChannel(SocketChannel ch) throws Exception {
21 | ChannelPipeline p = ch.pipeline();
22 | p.addLast(new StringEncoder());
23 | p.addLast(new StringDecoder());
24 | p.addLast(new ChannelInboundHandlerAdapter() {
25 | @Override
26 | public void channelActive(ChannelHandlerContext ctx)
27 | throws Exception {
28 | //on ready to send
29 | ctx.writeAndFlush(msg);
30 | }
31 | @Override
32 | public void channelRead(ChannelHandlerContext ctx,
33 | Object data) throws Exception {
34 | //on receive
35 | System.out.println("got " + data);
36 | }
37 | });
38 | }
39 | };
40 | BootstrapTemplate.newClientBootstrap(HOST, PORT, initializer );
41 | Thread.sleep(5000);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe3/PurchaseClient.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe3;
2 |
3 | import io.netty.channel.ChannelHandler;
4 | import io.netty.channel.ChannelInitializer;
5 | import io.netty.channel.ChannelPipeline;
6 | import io.netty.channel.socket.SocketChannel;
7 | import netty.cookbook.common.BootstrapTemplate;
8 | import netty.cookbook.common.CallbackProcessor;
9 |
10 | public class PurchaseClient {
11 | String host; int port;
12 | public PurchaseClient(String host, int port) {
13 | super();
14 | this.host = host;
15 | this.port = port;
16 | }
17 | public PurchaseClient send(PurchaseData message, CallbackProcessor asynchCall) throws Exception{
18 | ChannelHandler clientHandler = new PurchaseClientHandler(message, asynchCall);
19 | ChannelInitializer initializer = new ChannelInitializer() {
20 | @Override
21 | public void initChannel(SocketChannel ch) throws Exception {
22 | ChannelPipeline p = ch.pipeline();
23 | p.addLast(new PurchaseDataDecoder());
24 | p.addLast(new PurchaseDataEncoder());
25 | p.addLast(clientHandler);
26 | }
27 | };
28 | BootstrapTemplate.newClientBootstrap(host, port, initializer );
29 | return this;
30 | }
31 | public static void main(String[] args) throws Exception {
32 | int unixTime = (int) (System.currentTimeMillis() / 1000L);
33 | PurchaseData data = new PurchaseData(1001, 499.99f, "Trieu", "Amazon", unixTime, false );
34 | new PurchaseClient("127.0.0.1",8007).send(data, rs -> {
35 | System.out.println(rs);
36 | });
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe3/PurchaseData.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe3;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.gson.Gson;
6 |
7 | public class PurchaseData implements Serializable{
8 | private static final long serialVersionUID = -5467453661148034694L;
9 | private final int itemId;
10 | private final float price;
11 | private final String buyer;
12 | private final String seller;
13 | private final int unixTime;
14 | private final boolean processed;
15 | public PurchaseData(int itemId, float price, String buyer, String seller,
16 | int unixTime, boolean processed) {
17 | super();
18 | this.itemId = itemId;
19 | this.price = price;
20 | this.buyer = buyer;
21 | this.seller = seller;
22 | this.unixTime = unixTime;
23 | this.processed = processed;
24 | }
25 | public PurchaseData(Object obj, boolean processed) {
26 | super();
27 | PurchaseData data = (PurchaseData)obj;
28 | this.itemId = data.itemId;
29 | this.price = data.price;
30 | this.buyer = data.buyer;
31 | this.seller = data.seller;
32 | this.unixTime = data.unixTime;
33 | this.processed = processed;
34 | }
35 | public float getPrice() {
36 | return price;
37 | }
38 | public String getBuyer() {
39 | return buyer;
40 | }
41 | public String getSeller() {
42 | return seller;
43 | }
44 | public int getUnixTime() {
45 | return unixTime;
46 | }
47 | public int getItemId() {
48 | return itemId;
49 | }
50 | public boolean isProcessed() {
51 | return processed;
52 | }
53 | @Override
54 | public String toString() {
55 | return new Gson().toJson(this);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe3/PurchaseDataDecoder.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe3;
2 |
3 | import chapter2.recipe6.NettyMonitorIO;
4 | import io.netty.buffer.ByteBuf;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.handler.codec.serialization.ClassResolvers;
7 | import io.netty.handler.codec.serialization.ObjectDecoder;
8 |
9 | public class PurchaseDataDecoder extends ObjectDecoder {
10 | public PurchaseDataDecoder() {
11 | super(ClassResolvers.weakCachingConcurrentResolver(null));
12 | }
13 | @Override
14 | protected Object decode(ChannelHandlerContext ctx, ByteBuf buf)
15 | throws Exception {
16 | Object object = super.decode(ctx, buf);
17 | NettyMonitorIO.updateDataIn(buf);
18 | return object;
19 | }
20 | }
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe3/PurchaseDataEncoder.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe3;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.handler.codec.serialization.ObjectEncoder;
6 |
7 | import java.io.Serializable;
8 |
9 | import chapter2.recipe6.NettyMonitorIO;
10 |
11 | public class PurchaseDataEncoder extends ObjectEncoder {
12 | @Override
13 | protected void encode(ChannelHandlerContext ctx, Serializable msg, ByteBuf buf) throws Exception {
14 | super.encode(ctx, msg, buf);
15 | NettyMonitorIO.updateDataOut(buf);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe3/PurchaseServer.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe3;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.socket.SocketChannel;
8 | import netty.cookbook.common.BootstrapTemplate;
9 |
10 | import org.apache.log4j.Logger;
11 |
12 | public class PurchaseServer {
13 | final static Logger logger = Logger.getLogger(PurchaseServer.class);
14 |
15 | static final int PORT = 8007;
16 | static final String HOST = "127.0.0.1";
17 |
18 | public static void main(String[] args) throws Exception {
19 | ChannelInitializer initializer = new ChannelInitializer() {
20 | @Override
21 | public void initChannel(SocketChannel ch) throws Exception {
22 | ChannelPipeline p = ch.pipeline();
23 | p.addLast(new PurchaseDataDecoder());
24 | p.addLast(new PurchaseDataEncoder());
25 | p.addLast(new ChannelInboundHandlerAdapter() {
26 | @Override
27 | public void channelRead(ChannelHandlerContext ctx,
28 | Object data) throws Exception {
29 | System.out.println("processed Purchase " + data);
30 | PurchaseData processed = new PurchaseData(data, true);
31 | ctx.writeAndFlush(processed);
32 | }
33 | });
34 | }
35 | };
36 | BootstrapTemplate.newServerBootstrap(HOST, PORT, initializer);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe6/NettyMonitorIO.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe6;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | import java.text.DateFormat;
6 | import java.text.SimpleDateFormat;
7 | import java.util.Date;
8 | import java.util.Timer;
9 | import java.util.TimerTask;
10 | import java.util.concurrent.ConcurrentHashMap;
11 | import java.util.concurrent.ConcurrentMap;
12 |
13 | /**
14 | * @author trieunt
15 | *
16 | */
17 | public class NettyMonitorIO {
18 | static final DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
19 | static ConcurrentMap dataOutStats = new ConcurrentHashMap();
20 | static ConcurrentMap dataInStats = new ConcurrentHashMap();
21 | public static long updateDataOut(ByteBuf buf) {
22 | String time = DATE_TIME_FORMAT.format(new Date());
23 | long c = dataOutStats.getOrDefault(time, 0L) + buf.readableBytes();
24 | dataOutStats.put(time, c);
25 | return c;
26 | }
27 | public static long updateDataIn(ByteBuf buf) {
28 | String time = DATE_TIME_FORMAT.format(new Date());
29 | long c = dataInStats.getOrDefault(time, 0L) + buf.writableBytes();
30 | dataInStats.put(time, c);
31 | return c;
32 | }
33 | static {
34 | new Timer(true).schedule(new TimerTask() {
35 | @Override
36 | public void run() {
37 | System.out.println("--------------------------------");
38 | System.out.println("Data In Stats:");
39 | dataInStats.forEach((String key, Long val)->{
40 | System.out.println(key + " : "+val);
41 | });
42 | System.out.println("Data Out Stats:");
43 | dataOutStats.forEach((String key, Long val)->{
44 | System.out.println(key + " : "+val);
45 | });
46 | }
47 | }, 2000, 2000);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe7/HeartBeatHandler.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe7;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.buffer.Unpooled;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.channel.SimpleChannelInboundHandler;
7 | import io.netty.channel.socket.DatagramPacket;
8 | import io.netty.util.CharsetUtil;
9 |
10 | import java.util.Date;
11 | import java.util.LinkedList;
12 | import java.util.Queue;
13 | import java.util.Timer;
14 | import java.util.TimerTask;
15 |
16 | public class HeartBeatHandler extends
17 | SimpleChannelInboundHandler {
18 | private static final Queue logQueue = new LinkedList();
19 | static String log(String log) {
20 | return String.valueOf(logQueue.add(log));
21 | }
22 | static {
23 | new Timer(true).schedule(new TimerTask() {
24 | @Override
25 | public void run() {
26 | while ( ! logQueue.isEmpty() ) {
27 | // log to Kafka or somewhere
28 | String s = logQueue.poll();
29 | if(s != null){
30 | System.out.println(s);
31 | }
32 | }
33 | }
34 | }, 1000, 2000);
35 | }
36 |
37 | @Override
38 | public void channelReadComplete(ChannelHandlerContext ctx) {
39 | ctx.flush();
40 | }
41 |
42 | @Override
43 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
44 | cause.printStackTrace();
45 | // We don't close the channel because we can keep serving requests.
46 | }
47 |
48 | @Override
49 | protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
50 | System.err.println(packet);
51 | String s = packet.content().toString(CharsetUtil.UTF_8);
52 | System.out.println(s);
53 | ByteBuf buf = Unpooled.copiedBuffer("I'm alive at "+new Date(), CharsetUtil.UTF_8);
54 | ctx.write(new DatagramPacket(buf, packet.sender()));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe7/ImportantServer.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe7;
2 |
3 | import io.netty.channel.EventLoopGroup;
4 | import io.netty.channel.nio.NioEventLoopGroup;
5 | import netty.cookbook.common.BootstrapTemplate;
6 |
7 | /**
8 | * @author trieu
9 | *
10 | * demo for HeartBeat monitor
11 | *
12 | */
13 | public class ImportantServer {
14 | private static final int PORT = 8080;
15 | public static void main(String[] args) throws Exception {
16 | EventLoopGroup loopGroup = new NioEventLoopGroup();
17 | try {
18 | BootstrapTemplate.newBootstrapUDP(loopGroup, new HeartBeatHandler(), PORT)
19 | .sync().channel().closeFuture().await();
20 | } finally {
21 | loopGroup.shutdownGracefully();
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe8/SimpleSctpClient.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe8;
2 |
3 | import io.netty.bootstrap.Bootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.EventLoopGroup;
8 | import io.netty.channel.nio.NioEventLoopGroup;
9 | import io.netty.channel.sctp.SctpChannel;
10 | import io.netty.channel.sctp.SctpChannelOption;
11 | import io.netty.channel.sctp.nio.NioSctpChannel;
12 |
13 |
14 | public final class SimpleSctpClient {
15 |
16 | static final String HOST = System.getProperty("host", "127.0.0.1");
17 | static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
18 |
19 | public static void main(String[] args) throws Exception {
20 | EventLoopGroup loopGroup = new NioEventLoopGroup();
21 | try {
22 | ChannelFuture f = new Bootstrap().group(loopGroup)
23 | .channel(NioSctpChannel.class)
24 | // set SCTP option
25 | .option(SctpChannelOption.SCTP_NODELAY, true)
26 | .handler(new ChannelInitializer() {
27 | @Override
28 | public void initChannel(SctpChannel ch) throws Exception {
29 | ChannelPipeline p = ch.pipeline();
30 | p.addLast(new SimpleSctpClientHandler());
31 | }
32 | }).connect(HOST, PORT).sync();
33 | f.channel().closeFuture().sync();
34 | } finally {
35 | loopGroup.shutdownGracefully();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe8/SimpleSctpClientHandler.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe8;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.buffer.Unpooled;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.channel.ChannelInboundHandlerAdapter;
7 | import io.netty.channel.sctp.SctpMessage;
8 | import io.netty.util.CharsetUtil;
9 |
10 |
11 | public class SimpleSctpClientHandler extends ChannelInboundHandlerAdapter {
12 | private final ByteBuf firstMessage, secondMessage;
13 | public SimpleSctpClientHandler() {
14 | firstMessage = Unpooled.copiedBuffer("first message",CharsetUtil.UTF_8);
15 | secondMessage = Unpooled.copiedBuffer("second message",CharsetUtil.UTF_8);
16 | }
17 | @Override
18 | public void channelActive(ChannelHandlerContext ctx) {
19 | ctx.write(new SctpMessage(0, 0, firstMessage));
20 | ctx.write(new SctpMessage(0, 0, secondMessage));
21 | ctx.flush();
22 | }
23 |
24 | @Override
25 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
26 | System.out.println(msg);
27 | }
28 |
29 | @Override
30 | public void channelReadComplete(ChannelHandlerContext ctx) {
31 | ctx.flush();
32 | }
33 |
34 | @Override
35 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
36 | // Close the connection when an exception is raised.
37 | cause.printStackTrace();
38 | ctx.close();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe8/SimpleSctpServer.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe8;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelOption;
7 | import io.netty.channel.ChannelPipeline;
8 | import io.netty.channel.EventLoopGroup;
9 | import io.netty.channel.nio.NioEventLoopGroup;
10 | import io.netty.channel.sctp.SctpChannel;
11 | import io.netty.channel.sctp.nio.NioSctpServerChannel;
12 | import io.netty.handler.logging.LogLevel;
13 | import io.netty.handler.logging.LoggingHandler;
14 |
15 |
16 | public final class SimpleSctpServer {
17 |
18 | static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
19 |
20 | public static void main(String[] args) throws Exception {
21 | EventLoopGroup mainLoop = new NioEventLoopGroup(1);
22 | EventLoopGroup workerLoop = new NioEventLoopGroup();
23 | try {
24 | ChannelFuture f = new ServerBootstrap().group(mainLoop, workerLoop)
25 | .channel(NioSctpServerChannel.class)
26 | .option(ChannelOption.SO_BACKLOG, 100)
27 | .handler(new LoggingHandler(LogLevel.INFO))
28 | .childHandler(new ChannelInitializer() {
29 | @Override
30 | public void initChannel(SctpChannel ch) throws Exception {
31 | ChannelPipeline p = ch.pipeline();
32 | p.addLast(new SimpleSctpServerHandler());
33 | }
34 | }).bind(PORT).sync();
35 | f.channel().closeFuture().sync();
36 | } finally {
37 | mainLoop.shutdownGracefully();
38 | workerLoop.shutdownGracefully();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe8/SimpleSctpServerHandler.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe8;
2 |
3 | import io.netty.channel.ChannelHandler.Sharable;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 | import io.netty.channel.sctp.SctpMessage;
7 | import io.netty.util.CharsetUtil;
8 |
9 | /**
10 | * Handler implementation for the SCTP echo server.
11 | */
12 | @Sharable
13 | public class SimpleSctpServerHandler extends ChannelInboundHandlerAdapter {
14 | @Override
15 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
16 | System.out.println(msg);
17 | if(msg instanceof SctpMessage){
18 | SctpMessage sctpMsg = (SctpMessage) msg;
19 | System.out.println(sctpMsg.content().toString(CharsetUtil.UTF_8));
20 | ctx.write(sctpMsg);
21 | }
22 | }
23 |
24 | @Override
25 | public void channelReadComplete(ChannelHandlerContext ctx) {
26 | ctx.flush();
27 | }
28 |
29 | @Override
30 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
31 | // Close the connection when an exception is raised.
32 | cause.printStackTrace();
33 | ctx.close();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe9/FileReceiver.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe9;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.nio.file.Files;
7 |
8 | import com.butor.netty.handler.codec.ftp.DataReceiver;
9 |
10 | class FileReceiver implements DataReceiver {
11 | @Override
12 | public void receive(String name, InputStream data) throws IOException {
13 | System.out.println("got file: [" + name + "]");
14 | //copy to local folder
15 | Files.copy(data, new File("./data/"+name).toPath());
16 | }
17 | }
--------------------------------------------------------------------------------
/chapter2/src/main/java/chapter2/recipe9/SimpleServerFTP.java:
--------------------------------------------------------------------------------
1 | package chapter2.recipe9;
2 |
3 | import io.netty.channel.ChannelInitializer;
4 | import io.netty.channel.ChannelPipeline;
5 | import io.netty.channel.socket.SocketChannel;
6 | import netty.cookbook.common.BootstrapTemplate;
7 |
8 | import com.butor.netty.handler.codec.ftp.CrlfStringDecoder;
9 | import com.butor.netty.handler.codec.ftp.DataReceiver;
10 | import com.butor.netty.handler.codec.ftp.FtpServerHandler;
11 | import com.butor.netty.handler.codec.ftp.cmd.DefaultCommandExecutionTemplate;
12 |
13 | public class SimpleServerFTP {
14 | public static void main(String... args) throws Exception {
15 | DataReceiver dataReceiver = new FileReceiver();
16 | final DefaultCommandExecutionTemplate tpl = new DefaultCommandExecutionTemplate(dataReceiver);
17 | ChannelInitializer initializer = new ChannelInitializer() {
18 | @Override
19 | protected void initChannel(SocketChannel ch) throws Exception {
20 | ChannelPipeline p = ch.pipeline();
21 | p.addLast(new CrlfStringDecoder());
22 | p.addLast(new FtpServerHandler(tpl));
23 | }
24 | };
25 | BootstrapTemplate.newServerBootstrap("127.0.0.1", 2121, initializer);
26 | }
27 | }
--------------------------------------------------------------------------------
/chapter2/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter2/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter2/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/chapter2/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter2/tools/avro-tools-1.7.7.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/chapter2/tools/avro-tools-1.7.7.jar
--------------------------------------------------------------------------------
/chapter3/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter3/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | chapter3
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter3/README.md:
--------------------------------------------------------------------------------
1 | Netty Cookbook - chapter 3 code
--------------------------------------------------------------------------------
/chapter3/configs/redis-connection-pool-configs.json:
--------------------------------------------------------------------------------
1 | {
2 | maxTotal : 3000,
3 | maxIdle : 20,
4 | minIdle : 2,
5 | maxWaitMillis : 5000;
6 | numTestsPerEvictionRun : 10,
7 | testOnBorrow : true,
8 | testOnReturn : true,
9 | testWhileIdle : true,
10 | timeBetweenEvictionRunsMillis : 60000
11 | }
--------------------------------------------------------------------------------
/chapter3/lib/DateAdapterJ-1.1.3-20141216.175259-8.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/chapter3/lib/DateAdapterJ-1.1.3-20141216.175259-8.jar
--------------------------------------------------------------------------------
/chapter3/lib/RestExpress-0.11.0-20150113.201733-1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/chapter3/lib/RestExpress-0.11.0-20150113.201733-1.jar
--------------------------------------------------------------------------------
/chapter3/lib/RestExpress-Common-0.11.0-20150113.201714-1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/chapter3/lib/RestExpress-Common-0.11.0-20150113.201714-1.jar
--------------------------------------------------------------------------------
/chapter3/lib/alpn-boot-8.1.0.v20141016.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/chapter3/lib/alpn-boot-8.1.0.v20141016.jar
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe1/UriMatcher.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe1;
2 |
3 | public interface UriMatcher {
4 | public boolean match(String uri);
5 | }
6 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe2/HttpServerSpringMVC.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe2;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.nio.NioEventLoopGroup;
5 | import io.netty.channel.socket.nio.NioServerSocketChannel;
6 |
7 | public class HttpServerSpringMVC {
8 | private final String host;
9 | private final int port;
10 |
11 | public HttpServerSpringMVC(String host,int port) {
12 | this.host = host;
13 | this.port = port;
14 | }
15 |
16 | public void run() throws Exception {
17 | ServerBootstrap server = new ServerBootstrap();
18 | NioEventLoopGroup pGroup = new NioEventLoopGroup();
19 | NioEventLoopGroup cGroup = new NioEventLoopGroup();
20 | try {
21 | server.group(pGroup, cGroup)
22 | .channel(NioServerSocketChannel.class)
23 | .childHandler(new DispatcherServletChannelInitializer(WebConfig.class));
24 | server.bind(host, port).sync().channel().closeFuture().sync();
25 | }
26 | finally {
27 | cGroup.shutdownGracefully();
28 | pGroup.shutdownGracefully();
29 | }
30 | }
31 |
32 | public static void main(String[] args) throws Exception {
33 | String host;
34 | int port;
35 | if (args.length > 0) {
36 | host = args[0];
37 | port = Integer.parseInt(args[1]);
38 | } else {
39 | host = "127.0.0.1";
40 | port = 8080;
41 | }
42 | new HttpServerSpringMVC(host, port).run();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe2/TemplateConfiguration.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe2;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.servlet.ViewResolver;
6 | import org.thymeleaf.spring4.SpringTemplateEngine;
7 | import org.thymeleaf.spring4.view.ThymeleafViewResolver;
8 | import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
9 |
10 | @Configuration
11 | public class TemplateConfiguration {
12 | private static final String HTML_EXT = ".html";
13 | private static final String TEMPLATE_FOLDER = "templates/";
14 | private static final String XHTML = "XHTML";
15 |
16 | @Bean
17 | public ViewResolver viewResolver() {
18 | ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
19 | templateResolver.setTemplateMode(XHTML);
20 | templateResolver.setPrefix(TEMPLATE_FOLDER);
21 | templateResolver.setSuffix(HTML_EXT);
22 | SpringTemplateEngine engine = new SpringTemplateEngine();
23 | engine.setTemplateResolver(templateResolver);
24 | ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
25 | viewResolver.setTemplateEngine(engine);
26 | return viewResolver;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe2/WebConfig.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe2;
2 |
3 | import org.springframework.context.annotation.ComponentScan;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.servlet.config.annotation.EnableWebMvc;
6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
7 |
8 |
9 | @Configuration
10 | @EnableWebMvc
11 | @ComponentScan(basePackages=WebConfig.BASE_PACKAGE_NAME)
12 | public class WebConfig extends WebMvcConfigurerAdapter {
13 | static final String BASE_PACKAGE_NAME = "chapter3.recipe2";
14 | }
15 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe3/HttpFileServer.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe3;
2 |
3 | import netty.cookbook.common.NettyServerUtil;
4 |
5 | public class HttpFileServer {
6 |
7 | public static void main(String[] args) throws Exception {
8 | int port = 8080;
9 | String ip = "127.0.01";
10 | NettyServerUtil.newHttpServerBootstrap(ip, port, new HttpStaticFileServerHandler() );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe4/NettyHttpServerWithCORS.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe4;
2 |
3 | import static io.netty.handler.codec.http.HttpMethod.DELETE;
4 | import static io.netty.handler.codec.http.HttpMethod.GET;
5 | import static io.netty.handler.codec.http.HttpMethod.POST;
6 | import static io.netty.handler.codec.http.HttpMethod.PUT;
7 | import io.netty.channel.ChannelInitializer;
8 | import io.netty.channel.ChannelPipeline;
9 | import io.netty.channel.socket.SocketChannel;
10 | import io.netty.handler.codec.http.HttpObjectAggregator;
11 | import io.netty.handler.codec.http.HttpRequestDecoder;
12 | import io.netty.handler.codec.http.HttpResponseEncoder;
13 | import io.netty.handler.codec.http.cors.CorsConfig;
14 | import io.netty.handler.codec.http.cors.CorsHandler;
15 | import io.netty.handler.stream.ChunkedWriteHandler;
16 | import netty.cookbook.common.NettyServerUtil;
17 |
18 | public class NettyHttpServerWithCORS {
19 |
20 | public static void main(String[] args) {
21 | String ip = "127.0.0.1";
22 | int port = 8080;
23 | ChannelInitializer channelInit = new ChannelInitializer() {
24 | @Override
25 | protected void initChannel(SocketChannel ch) throws Exception {
26 | ChannelPipeline p = ch.pipeline();
27 |
28 | CorsConfig corsConfig = CorsConfig.withAnyOrigin()
29 | .allowedRequestHeaders("content-type","accept","MyCustomHeader")
30 | .allowedRequestMethods(PUT,POST,GET,DELETE)
31 | .build();
32 |
33 | p.addLast(new HttpResponseEncoder());
34 | p.addLast(new HttpRequestDecoder());
35 | p.addLast(new HttpObjectAggregator(65536));
36 | p.addLast(new ChunkedWriteHandler());
37 | p.addLast(new CorsHandler(corsConfig));
38 | p.addLast(new SimpleCORSHandler());
39 | }
40 | };
41 | NettyServerUtil.newHttpServerBootstrap(ip, port, channelInit);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe5/HttpServerSPDY.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe5;
2 |
3 | import io.netty.channel.ChannelInitializer;
4 | import io.netty.channel.ChannelPipeline;
5 | import io.netty.channel.socket.SocketChannel;
6 | import io.netty.handler.codec.spdy.SpdyOrHttpChooser.SelectedProtocol;
7 | import io.netty.handler.ssl.ApplicationProtocolConfig;
8 | import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
9 | import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
10 | import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
11 | import io.netty.handler.ssl.IdentityCipherSuiteFilter;
12 | import io.netty.handler.ssl.SslContext;
13 | import io.netty.handler.ssl.util.SelfSignedCertificate;
14 | import netty.cookbook.common.NettyServerUtil;
15 |
16 | public class HttpServerSPDY {
17 |
18 | //http://www.chromium.org/spdy
19 |
20 | public static void main(String[] args) throws Exception {
21 | String ip = "127.0.0.1";
22 | int port = 8080;
23 | // Configure SSL.
24 | SelfSignedCertificate ssc = new SelfSignedCertificate();
25 | final SslContext sslCtx = SslContext.newServerContext(
26 | ssc.certificate(), ssc.privateKey(), null, null,
27 | IdentityCipherSuiteFilter.INSTANCE,
28 | new ApplicationProtocolConfig(Protocol.ALPN,
29 | SelectorFailureBehavior.FATAL_ALERT,
30 | SelectedListenerFailureBehavior.FATAL_ALERT,
31 | SelectedProtocol.SPDY_3_1.protocolName(),
32 | SelectedProtocol.HTTP_1_1.protocolName()), 0, 0);
33 |
34 | ChannelInitializer channelInit = new ChannelInitializer() {
35 | @Override
36 | protected void initChannel(SocketChannel ch) throws Exception {
37 | ChannelPipeline p = ch.pipeline();
38 | p.addLast(sslCtx.newHandler(ch.alloc()));
39 | p.addLast(new SpdyOrHttpHandler());
40 | }
41 | };
42 | NettyServerUtil.newHttpServerBootstrap(ip, port, channelInit);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe5/SpdyOrHttpHandler.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe5;
2 |
3 | import io.netty.channel.ChannelInboundHandler;
4 | import io.netty.handler.codec.spdy.SpdyOrHttpChooser;
5 |
6 | public class SpdyOrHttpHandler extends SpdyOrHttpChooser {
7 | private static final int MAX_CONTENT_LENGTH = 1024 * 100;
8 | public SpdyOrHttpHandler() {
9 | this(MAX_CONTENT_LENGTH, MAX_CONTENT_LENGTH);
10 | }
11 | public SpdyOrHttpHandler(int maxSpdyContentLength, int maxHttpContentLength) {
12 | super(maxSpdyContentLength, maxHttpContentLength);
13 | }
14 | @Override
15 | protected ChannelInboundHandler createHttpRequestHandlerForHttp() {
16 | return new SpdyServerHandler();
17 | }
18 | }
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe6/SimpleHttpRequest.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe6;
2 |
3 | import io.netty.handler.codec.http.Cookie;
4 | import io.netty.handler.codec.http.HttpHeaders;
5 |
6 | import java.util.List;
7 | import java.util.Map;
8 | import java.util.Set;
9 |
10 | import com.google.gson.Gson;
11 |
12 | public class SimpleHttpRequest {
13 | protected String uri = "";
14 | protected boolean notAuthorized;
15 | protected Set cookies;
16 | protected Map> parameters;
17 | protected HttpHeaders headers;
18 | protected byte[] body;
19 |
20 | public SimpleHttpRequest() {
21 | // TODO Auto-generated constructor stub
22 | }
23 |
24 | public SimpleHttpRequest(String uri) {
25 | super();
26 | this.uri = uri;
27 | }
28 |
29 | public SimpleHttpRequest(String uri, Map> parameters) {
30 | super();
31 | this.uri = uri;
32 | this.parameters = parameters;
33 | }
34 |
35 | public String getUri() {
36 | return uri;
37 | }
38 |
39 | public void setUri(String uri) {
40 | this.uri = uri;
41 | }
42 |
43 |
44 |
45 | public HttpHeaders getHeaders() {
46 | return headers;
47 | }
48 |
49 | public void setHeaders(HttpHeaders headers) {
50 | this.headers = headers;
51 | }
52 |
53 | public byte[] getBody() {
54 | return body;
55 | }
56 |
57 | public void setBody(byte[] body) {
58 | this.body = body;
59 | }
60 |
61 | public Map> getParameters() {
62 | return parameters;
63 | }
64 |
65 | public void setParameters(Map> parameters) {
66 | this.parameters = parameters;
67 | }
68 |
69 | public Set getCookies() {
70 | return cookies;
71 | }
72 |
73 | public void setCookies(Set cookies) {
74 | this.cookies = cookies;
75 | }
76 |
77 | public boolean isNotAuthorized() {
78 | return notAuthorized;
79 | }
80 |
81 | public void setNotAuthorized(boolean notAuthorized) {
82 | this.notAuthorized = notAuthorized;
83 | }
84 |
85 | @Override
86 | public String toString() {
87 | return new Gson().toJson(this);
88 | }
89 | }
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe6/SimpleHttpResponse.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe6;
2 |
3 | import netty.cookbook.common.http.ContentTypePool;
4 |
5 | import com.google.gson.Gson;
6 |
7 | public class SimpleHttpResponse {
8 | protected int status = 200;
9 | protected String contentType = ContentTypePool.TEXT_UTF8;
10 | protected String head;
11 | protected String body;
12 | protected long time;
13 |
14 | public SimpleHttpResponse() {
15 | // TODO Auto-generated constructor stub
16 | }
17 |
18 | public SimpleHttpResponse(String data) {
19 | super();
20 | this.body = data;
21 | }
22 |
23 | public int getStatus() {
24 | return status;
25 | }
26 |
27 | public void setStatus(int status) {
28 | this.status = status;
29 | }
30 |
31 | public String getContentType() {
32 | return contentType;
33 | }
34 |
35 | public void setContentType(String contentType) {
36 | this.contentType = contentType;
37 | }
38 |
39 | public String getHead() {
40 | return head;
41 | }
42 |
43 | public void setHead(String head) {
44 | this.head = head;
45 | }
46 |
47 | public String getBody() {
48 | return body;
49 | }
50 |
51 | public void setBody(String data) {
52 | this.body = data;
53 | }
54 |
55 | public long getTime() {
56 | return time;
57 | }
58 |
59 | public void setTime(long time) {
60 | this.time = time;
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | return new Gson().toJson(this);
66 | }
67 |
68 | }
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe6/functions/Decorator.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe6.functions;
2 |
3 | import java.util.function.UnaryOperator;
4 |
5 | import chapter3.recipe6.SimpleHttpResponse;
6 |
7 | @FunctionalInterface
8 | public interface Decorator extends UnaryOperator{
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe6/functions/Filter.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe6.functions;
2 |
3 | import java.util.function.UnaryOperator;
4 |
5 | import chapter3.recipe6.SimpleHttpRequest;
6 |
7 |
8 |
9 | @FunctionalInterface
10 | public interface Filter extends UnaryOperator {
11 |
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe6/functions/FinalProcessor.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe6.functions;
2 |
3 | import java.util.function.Function;
4 |
5 | import chapter3.recipe6.SimpleHttpRequest;
6 | import chapter3.recipe6.SimpleHttpResponse;
7 |
8 | @FunctionalInterface
9 | public interface FinalProcessor extends Function{
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/chapter3/recipe6/functions/Processor.java:
--------------------------------------------------------------------------------
1 | package chapter3.recipe6.functions;
2 |
3 | import java.util.function.Function;
4 |
5 | import chapter3.recipe6.SimpleHttpRequest;
6 | import chapter3.recipe6.SimpleHttpResponse;
7 |
8 | @FunctionalInterface
9 | public interface Processor extends Function{
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/CallbackActor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import akka.actor.UntypedActor;
4 |
5 | public class CallbackActor extends UntypedActor {
6 |
7 | @Override
8 | public void onReceive(Object arg0) throws Exception {
9 | // TODO Auto-generated method stub
10 |
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/JsOptimizerUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import com.google.javascript.jscomp.CompilationLevel;
4 | import com.google.javascript.jscomp.Compiler;
5 | import com.google.javascript.jscomp.CompilerOptions;
6 | import com.google.javascript.jscomp.SourceFile;
7 |
8 | /**
9 | * Google Closure compiler Util
10 | *
11 | * @author Trieu.nguyen
12 | *
13 | */
14 | public class JsOptimizerUtil {
15 | /**
16 | * @param code
17 | * JavaScript source code to compile.
18 | * @return The compiled version of the code.
19 | */
20 | public static String compile(String code) {
21 |
22 | // System.out.println("------------------------");
23 | // System.out.println(code);
24 | // System.out.println("------------------------");
25 |
26 | Compiler compiler = new Compiler();
27 |
28 | CompilerOptions options = new CompilerOptions();
29 | // Advanced mode is used here, but additional options could be set, too.
30 | CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
31 |
32 | // To get the complete set of externs, the logic in
33 | // CompilerRunner.getDefaultExterns() should be used here.
34 | SourceFile extern = SourceFile.fromCode("externs.js", "");
35 |
36 | // The dummy input name "input.js" is used here so that any warnings or
37 | // errors will cite line numbers in terms of input.js.
38 | SourceFile input = SourceFile.fromCode("input.js", code);
39 |
40 | // compile() returns a Result, but it is not needed here.
41 | compiler.compile(extern, input, options);
42 |
43 | // The compiler is responsible for generating the compiled code; it is
44 | // not
45 | // accessible via the Result.
46 | return compiler.toSource();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/NashornEngineUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.io.IOException;
4 | import java.nio.charset.StandardCharsets;
5 | import java.nio.file.Files;
6 | import java.nio.file.Paths;
7 |
8 | import javax.script.Compilable;
9 | import javax.script.CompiledScript;
10 | import javax.script.ScriptException;
11 | import javax.script.SimpleBindings;
12 |
13 | import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
14 | import chapter3.recipe6.SimpleHttpRequest;
15 | import chapter3.recipe6.SimpleHttpResponse;
16 |
17 | public class NashornEngineUtil {
18 | private static final NashornScriptEngineFactory engineFactory = new NashornScriptEngineFactory();
19 |
20 | public static SimpleHttpResponse process(SimpleHttpRequest httpRequest)
21 | throws NoSuchMethodException, ScriptException, IOException {
22 | CompiledScript compiled;
23 | Compilable engine;
24 | String scriptFilePath = "./src/main/resources/templates/js/script.js";
25 |
26 | engine = (Compilable) engineFactory.getScriptEngine();
27 | compiled = ((Compilable) engine).compile(Files.newBufferedReader(Paths.get(scriptFilePath),StandardCharsets.UTF_8));
28 |
29 | SimpleBindings global = new SimpleBindings();
30 | global.put("theReq", httpRequest);
31 | global.put("theResp", new SimpleHttpResponse());
32 |
33 | Object result = compiled.eval(global);
34 | SimpleHttpResponse resp = (SimpleHttpResponse) result;
35 | return resp;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/http/BasicHttpResponseHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.handler.codec.http.HttpRequest;
4 | import io.netty.handler.codec.http.HttpResponse;
5 | import io.netty.handler.codec.http.QueryStringDecoder;
6 |
7 | public class BasicHttpResponseHandler implements HttpEventHandler {
8 | final String data;
9 | final int status;
10 |
11 | public BasicHttpResponseHandler(String data, int status) {
12 | super();
13 | this.data = data;
14 | this.status = status;
15 | }
16 |
17 | public HttpResponse handle(HttpRequest req, QueryStringDecoder q)
18 | throws Exception {
19 | return HttpEventHandler.buildHttpResponse(data, status, ContentTypePool.TEXT_UTF8);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/http/ContentTypePool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | public class ContentTypePool {
4 | public static final String GIF = "image/gif";
5 | public static final String TRACKING_GIF = GIF;
6 | public static final String JPEG = "image/jpeg";
7 |
8 | public static final String JAVA_SCRIPT = "application/javascript; charset=utf-8";
9 | public static final String XML = "application/xml; charset=utf-8";
10 | public static final String JSON = "application/json; charset=utf-8";
11 |
12 | public static final String TEXT_UTF8 = "text/plain; charset=UTF-8";
13 | public static final String HTML_UTF8 = "text/html; charset=UTF-8";
14 | }
15 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/http/HttpEventProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.handler.codec.http.HttpRequest;
4 | import io.netty.handler.codec.http.QueryStringDecoder;
5 |
6 | public class HttpEventProcessor {
7 | final HttpRequest req;
8 | final QueryStringDecoder query;
9 |
10 | public HttpEventProcessor(HttpRequest req, QueryStringDecoder query) {
11 | super();
12 | this.req = req;
13 | this.query = query;
14 | }
15 |
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/http/HttpOutputResource.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class HttpOutputResource {
6 | ByteBuf byteBuf;
7 | long length;
8 | long lastModified;
9 |
10 |
11 | public HttpOutputResource(ByteBuf byteBuf, long lastModified) {
12 | super();
13 | this.byteBuf = byteBuf;
14 | this.length = byteBuf.readableBytes();
15 | this.lastModified = lastModified;
16 | }
17 |
18 | public ByteBuf getByteBuf() {
19 | return byteBuf;
20 | }
21 |
22 | public void setByteBuf(ByteBuf byteBuf) {
23 | this.byteBuf = byteBuf;
24 | }
25 |
26 | public long getLength() {
27 | return length;
28 | }
29 |
30 | public void setLength(long length) {
31 | this.length = length;
32 | }
33 |
34 | public long getLastModified() {
35 | return lastModified;
36 | }
37 |
38 | public void setLastModified(long lastModified) {
39 | this.lastModified = lastModified;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/redis/RedisCommand.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import netty.cookbook.common.StringPool;
4 | import redis.clients.jedis.Jedis;
5 | import redis.clients.jedis.ShardedJedis;
6 | import redis.clients.jedis.ShardedJedisPool;
7 | import redis.clients.jedis.exceptions.JedisException;
8 |
9 | public abstract class RedisCommand {
10 | protected ShardedJedisPool jedisPool;
11 | protected ShardedJedis shardedJedis = null;
12 | protected Jedis jedis = null;
13 |
14 | public RedisCommand(ShardedJedisPool jedisPool) {
15 | super();
16 | if (jedisPool == null) {
17 | throw new IllegalArgumentException("jedisPool is NULL!");
18 | }
19 | this.jedisPool = jedisPool;
20 | }
21 |
22 | public T execute() {
23 | boolean commited = false;
24 | T rs = null;
25 | try {
26 | shardedJedis = jedisPool.getResource();
27 | if (shardedJedis != null) {
28 | jedis = shardedJedis.getShard(StringPool.BLANK);
29 | rs = build();
30 | commited = true;
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | } finally {
35 | freeRedisResource(jedisPool, shardedJedis, commited);
36 | }
37 | return rs;
38 | }
39 |
40 | public static void freeRedisResource(ShardedJedisPool jedisPool, ShardedJedis shardedJedis, boolean isCommited){
41 | if (shardedJedis != null && jedisPool != null) {
42 | if (isCommited) {
43 | jedisPool.returnResource(shardedJedis);
44 | } else {
45 | jedisPool.returnBrokenResource(shardedJedis);
46 | }
47 | }
48 | }
49 |
50 | //define the logic at implementer
51 | protected abstract T build() throws JedisException;
52 | }
--------------------------------------------------------------------------------
/chapter3/src/main/java/netty/cookbook/common/redis/RedisInfo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import redis.clients.jedis.JedisShardInfo;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | public class RedisInfo {
10 | public static final String LOCALHOST_STR = "localhost";
11 |
12 | private String host;
13 | private int port;
14 | private String auth;
15 | private ShardedJedisPool shardedJedisPool;
16 |
17 | protected void initThePool(){
18 | List shardInfos = new ArrayList(1);
19 | shardInfos.add(new JedisShardInfo(getHost(), getPort(), 0));
20 | shardedJedisPool = new ShardedJedisPool(RedisConnectionPoolConfig.getJedisPoolConfigInstance(), shardInfos);
21 | }
22 |
23 | public RedisInfo(String host, int port) {
24 | this.host = host;
25 | this.port = port;
26 | initThePool();
27 | }
28 |
29 | public RedisInfo(String host, int port,String auth) {
30 | this.host = host;
31 | this.port = port;
32 | this.auth = auth;
33 | initThePool();
34 | }
35 |
36 | public String getHost() {
37 | return host;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public String getAuth() {
45 | return auth;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (obj instanceof RedisInfo) {
51 | RedisInfo hp = (RedisInfo) obj;
52 |
53 | String thisHost = convertHost(host);
54 | String hpHost = convertHost(hp.host);
55 | return port == hp.port && thisHost.equals(hpHost);
56 |
57 | }
58 |
59 | return false;
60 | }
61 |
62 | public ShardedJedisPool getShardedJedisPool() {
63 | return shardedJedisPool;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return host + ":" + port;
69 | }
70 |
71 | private String convertHost(String host) {
72 | if (host.equals("127.0.0.1"))
73 | return LOCALHOST_STR;
74 | else if (host.equals("::1"))
75 | return LOCALHOST_STR;
76 |
77 | return host;
78 | }
79 | }
--------------------------------------------------------------------------------
/chapter3/src/main/resources/templates/hello-view.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello SpringMVC with Netty
5 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
28 |
29 |
--------------------------------------------------------------------------------
/chapter3/src/main/resources/templates/js/script.js:
--------------------------------------------------------------------------------
1 | var fun1 = function(name) {
2 | print('Hi there from Javascript, ' + name);
3 | return "greetings from javascript";
4 | };
5 |
6 | var router = function (req, resp) {
7 | //print("req: " + Object.prototype.toString.call(req));
8 | resp.data = "hello from JS Nashorn Engine";
9 | //resp.time = new Date().getTime();
10 | return resp;
11 | };
12 |
13 | router(theReq, theResp)
14 |
15 | /*
16 | load('http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js');
17 |
18 | var odds = _.filter([1, 2, 3, 4, 5, 6], function (num) {
19 | return num % 2 == 1;
20 | });
21 |
22 | print(odds); // 1, 3, 5
23 | */
--------------------------------------------------------------------------------
/chapter4/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter4/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | chapter4
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter4/README.md:
--------------------------------------------------------------------------------
1 | Netty Cookbook - chapter 4 code
--------------------------------------------------------------------------------
/chapter4/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 |
4 | sourceCompatibility = 1.8
5 |
6 | version = '1.0'
7 |
8 | repositories {
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | compile (
14 | // common
15 | 'io.netty:netty-all:4.0.25.Final'
16 | ,'commons-io:commons-io:2.4'
17 | ,'org.apache.commons:commons-lang3:3.3.2'
18 | ,'log4j:log4j:1.2.17'
19 | ,'org.slf4j:slf4j-log4j12:1.7.7'
20 | ,'org.yaml:snakeyaml:1.14'
21 |
22 | ,'com.google.code.gson:gson:2.3'
23 | ,'com.google.guava:guava:18.0'
24 | ,'org.twitter4j:twitter4j-core:4.0.2'
25 | ,'org.twitter4j:twitter4j-stream:4.0.2'
26 | ,'redis.clients:jedis:2.6.2'
27 | ,'com.github.jknack:handlebars:2.0.0'
28 |
29 | ,'io.reactivex:rxnetty:0.4.6'
30 |
31 | )
32 | testCompile group: 'junit', name: 'junit', version: '4.11'
33 | }
34 |
--------------------------------------------------------------------------------
/chapter4/configs/redis-connection-pool-configs.json:
--------------------------------------------------------------------------------
1 | {
2 | maxTotal : 3000,
3 | maxIdle : 20,
4 | minIdle : 2,
5 | maxWaitMillis : 5000;
6 | numTestsPerEvictionRun : 10,
7 | testOnBorrow : true,
8 | testOnReturn : true,
9 | testWhileIdle : true,
10 | timeBetweenEvictionRunsMillis : 60000
11 | }
--------------------------------------------------------------------------------
/chapter4/src/main/java/chapter4/recipe1/WebSocketServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe1;
2 |
3 |
4 | /**
5 | * @author toddf
6 | * @since June 29, 2012
7 | */
8 | public class WebSocketServer {
9 |
10 |
11 | public static void main(String[] args) {
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter4/src/main/java/chapter4/recipe2/RealtimeWebSocketIO.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe2;
2 |
3 | public class RealtimeWebSocketIO {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/chapter4/recipe3/ChatServerWithSTOMP.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe3;
2 |
3 | public class ChatServerWithSTOMP {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/chapter4/recipe4/RealtimeWidgetServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe4;
2 |
3 | public class RealtimeWidgetServer {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/http/ContentTypePool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | public class ContentTypePool {
4 | public static final String GIF = "image/gif";
5 | public static final String TRACKING_GIF = GIF;
6 | public static final String JPEG = "image/jpeg";
7 |
8 | public static final String JAVA_SCRIPT = "application/javascript; charset=utf-8";
9 | public static final String XML = "application/xml; charset=utf-8";
10 | public static final String JSON = "application/json; charset=utf-8";
11 |
12 | public static final String TEXT_UTF8 = "text/plain; charset=UTF-8";
13 | public static final String HTML_UTF8 = "text/html; charset=UTF-8";
14 | }
15 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/http/HttpOutputResource.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class HttpOutputResource {
6 | ByteBuf byteBuf;
7 | long length;
8 | long lastModified;
9 |
10 |
11 | public HttpOutputResource(ByteBuf byteBuf, long lastModified) {
12 | super();
13 | this.byteBuf = byteBuf;
14 | this.length = byteBuf.readableBytes();
15 | this.lastModified = lastModified;
16 | }
17 |
18 | public ByteBuf getByteBuf() {
19 | return byteBuf;
20 | }
21 |
22 | public void setByteBuf(ByteBuf byteBuf) {
23 | this.byteBuf = byteBuf;
24 | }
25 |
26 | public long getLength() {
27 | return length;
28 | }
29 |
30 | public void setLength(long length) {
31 | this.length = length;
32 | }
33 |
34 | public long getLastModified() {
35 | return lastModified;
36 | }
37 |
38 | public void setLastModified(long lastModified) {
39 | this.lastModified = lastModified;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/redis/RedisCommand.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import netty.cookbook.common.StringPool;
4 | import redis.clients.jedis.Jedis;
5 | import redis.clients.jedis.ShardedJedis;
6 | import redis.clients.jedis.ShardedJedisPool;
7 | import redis.clients.jedis.exceptions.JedisException;
8 |
9 | public abstract class RedisCommand {
10 | protected ShardedJedisPool jedisPool;
11 | protected ShardedJedis shardedJedis = null;
12 | protected Jedis jedis = null;
13 |
14 | public RedisCommand(ShardedJedisPool jedisPool) {
15 | super();
16 | if (jedisPool == null) {
17 | throw new IllegalArgumentException("jedisPool is NULL!");
18 | }
19 | this.jedisPool = jedisPool;
20 | }
21 |
22 | public T execute() {
23 | boolean commited = false;
24 | T rs = null;
25 | try {
26 | shardedJedis = jedisPool.getResource();
27 | if (shardedJedis != null) {
28 | jedis = shardedJedis.getShard(StringPool.BLANK);
29 | rs = build();
30 | commited = true;
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | } finally {
35 | freeRedisResource(jedisPool, shardedJedis, commited);
36 | }
37 | return rs;
38 | }
39 |
40 | public static void freeRedisResource(ShardedJedisPool jedisPool, ShardedJedis shardedJedis, boolean isCommited){
41 | if (shardedJedis != null && jedisPool != null) {
42 | if (isCommited) {
43 | jedisPool.returnResource(shardedJedis);
44 | } else {
45 | jedisPool.returnBrokenResource(shardedJedis);
46 | }
47 | }
48 | }
49 |
50 | //define the logic at implementer
51 | protected abstract T build() throws JedisException;
52 | }
--------------------------------------------------------------------------------
/chapter4/src/main/java/netty/cookbook/common/redis/RedisInfo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import redis.clients.jedis.JedisShardInfo;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | public class RedisInfo {
10 | public static final String LOCALHOST_STR = "localhost";
11 |
12 | private String host;
13 | private int port;
14 | private String auth;
15 | private ShardedJedisPool shardedJedisPool;
16 |
17 | protected void initThePool(){
18 | List shardInfos = new ArrayList(1);
19 | shardInfos.add(new JedisShardInfo(getHost(), getPort(), 0));
20 | shardedJedisPool = new ShardedJedisPool(RedisConnectionPoolConfig.getJedisPoolConfigInstance(), shardInfos);
21 | }
22 |
23 | public RedisInfo(String host, int port) {
24 | this.host = host;
25 | this.port = port;
26 | initThePool();
27 | }
28 |
29 | public RedisInfo(String host, int port,String auth) {
30 | this.host = host;
31 | this.port = port;
32 | this.auth = auth;
33 | initThePool();
34 | }
35 |
36 | public String getHost() {
37 | return host;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public String getAuth() {
45 | return auth;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (obj instanceof RedisInfo) {
51 | RedisInfo hp = (RedisInfo) obj;
52 |
53 | String thisHost = convertHost(host);
54 | String hpHost = convertHost(hp.host);
55 | return port == hp.port && thisHost.equals(hpHost);
56 |
57 | }
58 |
59 | return false;
60 | }
61 |
62 | public ShardedJedisPool getShardedJedisPool() {
63 | return shardedJedisPool;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return host + ":" + port;
69 | }
70 |
71 | private String convertHost(String host) {
72 | if (host.equals("127.0.0.1"))
73 | return LOCALHOST_STR;
74 | else if (host.equals("::1"))
75 | return LOCALHOST_STR;
76 |
77 | return host;
78 | }
79 | }
--------------------------------------------------------------------------------
/chapter5/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter5/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | chapter5
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter5/README.md:
--------------------------------------------------------------------------------
1 | Netty Cookbook - chapter 5 code
--------------------------------------------------------------------------------
/chapter5/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 |
4 | sourceCompatibility = 1.8
5 |
6 | version = '1.0'
7 |
8 | repositories {
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | compile (
14 | // common
15 | 'io.netty:netty-all:4.0.25.Final'
16 | ,'commons-io:commons-io:2.4'
17 | ,'org.apache.commons:commons-lang3:3.3.2'
18 | ,'log4j:log4j:1.2.17'
19 | ,'org.slf4j:slf4j-log4j12:1.7.7'
20 | ,'org.yaml:snakeyaml:1.14'
21 |
22 | ,'com.google.code.gson:gson:2.3'
23 | ,'com.google.guava:guava:18.0'
24 | ,'org.twitter4j:twitter4j-core:4.0.2'
25 | ,'org.twitter4j:twitter4j-stream:4.0.2'
26 | ,'redis.clients:jedis:2.6.2'
27 | ,'com.github.jknack:handlebars:2.0.0'
28 |
29 | )
30 | testCompile group: 'junit', name: 'junit', version: '4.11'
31 | }
32 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/chapter4/recipe1/WebSocketServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe1;
2 |
3 |
4 | /**
5 | * @author toddf
6 | * @since June 29, 2012
7 | */
8 | public class WebSocketServer {
9 |
10 |
11 | public static void main(String[] args) {
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter5/src/main/java/chapter4/recipe2/RealtimeWebSocketIO.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe2;
2 |
3 | public class RealtimeWebSocketIO {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/chapter4/recipe3/ChatServerWithSTOMP.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe3;
2 |
3 | public class ChatServerWithSTOMP {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/chapter4/recipe4/RealtimeWidgetServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe4;
2 |
3 | public class RealtimeWidgetServer {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/http/ContentTypePool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | public class ContentTypePool {
4 | public static final String GIF = "image/gif";
5 | public static final String TRACKING_GIF = GIF;
6 | public static final String JPEG = "image/jpeg";
7 |
8 | public static final String JAVA_SCRIPT = "application/javascript; charset=utf-8";
9 | public static final String XML = "application/xml; charset=utf-8";
10 | public static final String JSON = "application/json; charset=utf-8";
11 |
12 | public static final String TEXT_UTF8 = "text/plain; charset=UTF-8";
13 | public static final String HTML_UTF8 = "text/html; charset=UTF-8";
14 | }
15 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/http/HttpOutputResource.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class HttpOutputResource {
6 | ByteBuf byteBuf;
7 | long length;
8 | long lastModified;
9 |
10 |
11 | public HttpOutputResource(ByteBuf byteBuf, long lastModified) {
12 | super();
13 | this.byteBuf = byteBuf;
14 | this.length = byteBuf.readableBytes();
15 | this.lastModified = lastModified;
16 | }
17 |
18 | public ByteBuf getByteBuf() {
19 | return byteBuf;
20 | }
21 |
22 | public void setByteBuf(ByteBuf byteBuf) {
23 | this.byteBuf = byteBuf;
24 | }
25 |
26 | public long getLength() {
27 | return length;
28 | }
29 |
30 | public void setLength(long length) {
31 | this.length = length;
32 | }
33 |
34 | public long getLastModified() {
35 | return lastModified;
36 | }
37 |
38 | public void setLastModified(long lastModified) {
39 | this.lastModified = lastModified;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/redis/RedisCommand.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import netty.cookbook.common.StringPool;
4 | import redis.clients.jedis.Jedis;
5 | import redis.clients.jedis.ShardedJedis;
6 | import redis.clients.jedis.ShardedJedisPool;
7 | import redis.clients.jedis.exceptions.JedisException;
8 |
9 | public abstract class RedisCommand {
10 | protected ShardedJedisPool jedisPool;
11 | protected ShardedJedis shardedJedis = null;
12 | protected Jedis jedis = null;
13 |
14 | public RedisCommand(ShardedJedisPool jedisPool) {
15 | super();
16 | if (jedisPool == null) {
17 | throw new IllegalArgumentException("jedisPool is NULL!");
18 | }
19 | this.jedisPool = jedisPool;
20 | }
21 |
22 | public T execute() {
23 | boolean commited = false;
24 | T rs = null;
25 | try {
26 | shardedJedis = jedisPool.getResource();
27 | if (shardedJedis != null) {
28 | jedis = shardedJedis.getShard(StringPool.BLANK);
29 | rs = build();
30 | commited = true;
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | } finally {
35 | freeRedisResource(jedisPool, shardedJedis, commited);
36 | }
37 | return rs;
38 | }
39 |
40 | public static void freeRedisResource(ShardedJedisPool jedisPool, ShardedJedis shardedJedis, boolean isCommited){
41 | if (shardedJedis != null && jedisPool != null) {
42 | if (isCommited) {
43 | jedisPool.returnResource(shardedJedis);
44 | } else {
45 | jedisPool.returnBrokenResource(shardedJedis);
46 | }
47 | }
48 | }
49 |
50 | //define the logic at implementer
51 | protected abstract T build() throws JedisException;
52 | }
--------------------------------------------------------------------------------
/chapter5/src/main/java/netty/cookbook/common/redis/RedisInfo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import redis.clients.jedis.JedisShardInfo;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | public class RedisInfo {
10 | public static final String LOCALHOST_STR = "localhost";
11 |
12 | private String host;
13 | private int port;
14 | private String auth;
15 | private ShardedJedisPool shardedJedisPool;
16 |
17 | protected void initThePool(){
18 | List shardInfos = new ArrayList(1);
19 | shardInfos.add(new JedisShardInfo(getHost(), getPort(), 0));
20 | shardedJedisPool = new ShardedJedisPool(RedisConnectionPoolConfig.getJedisPoolConfigInstance(), shardInfos);
21 | }
22 |
23 | public RedisInfo(String host, int port) {
24 | this.host = host;
25 | this.port = port;
26 | initThePool();
27 | }
28 |
29 | public RedisInfo(String host, int port,String auth) {
30 | this.host = host;
31 | this.port = port;
32 | this.auth = auth;
33 | initThePool();
34 | }
35 |
36 | public String getHost() {
37 | return host;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public String getAuth() {
45 | return auth;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (obj instanceof RedisInfo) {
51 | RedisInfo hp = (RedisInfo) obj;
52 |
53 | String thisHost = convertHost(host);
54 | String hpHost = convertHost(hp.host);
55 | return port == hp.port && thisHost.equals(hpHost);
56 |
57 | }
58 |
59 | return false;
60 | }
61 |
62 | public ShardedJedisPool getShardedJedisPool() {
63 | return shardedJedisPool;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return host + ":" + port;
69 | }
70 |
71 | private String convertHost(String host) {
72 | if (host.equals("127.0.0.1"))
73 | return LOCALHOST_STR;
74 | else if (host.equals("::1"))
75 | return LOCALHOST_STR;
76 |
77 | return host;
78 | }
79 | }
--------------------------------------------------------------------------------
/chapter6/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter6/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | chapter5
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter6/README.md:
--------------------------------------------------------------------------------
1 | Netty Cookbook - chapter 6 code
--------------------------------------------------------------------------------
/chapter6/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 |
4 | sourceCompatibility = 1.8
5 |
6 | version = '1.0'
7 |
8 | repositories {
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | compile (
14 | // common
15 | 'io.netty:netty-all:4.0.25.Final'
16 | ,'commons-io:commons-io:2.4'
17 | ,'org.apache.commons:commons-lang3:3.3.2'
18 | ,'log4j:log4j:1.2.17'
19 | ,'org.slf4j:slf4j-log4j12:1.7.7'
20 | ,'org.yaml:snakeyaml:1.14'
21 |
22 | ,'com.google.code.gson:gson:2.3'
23 | ,'com.google.guava:guava:18.0'
24 | ,'org.twitter4j:twitter4j-core:4.0.2'
25 | ,'org.twitter4j:twitter4j-stream:4.0.2'
26 | ,'redis.clients:jedis:2.6.2'
27 | ,'com.github.jknack:handlebars:2.0.0'
28 |
29 | )
30 | testCompile group: 'junit', name: 'junit', version: '4.11'
31 | }
32 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/chapter4/recipe1/WebSocketServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe1;
2 |
3 |
4 | /**
5 | * @author toddf
6 | * @since June 29, 2012
7 | */
8 | public class WebSocketServer {
9 |
10 |
11 | public static void main(String[] args) {
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter6/src/main/java/chapter4/recipe2/RealtimeWebSocketIO.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe2;
2 |
3 | public class RealtimeWebSocketIO {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/chapter4/recipe3/ChatServerWithSTOMP.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe3;
2 |
3 | public class ChatServerWithSTOMP {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/chapter4/recipe4/RealtimeWidgetServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe4;
2 |
3 | public class RealtimeWidgetServer {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/http/ContentTypePool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | public class ContentTypePool {
4 | public static final String GIF = "image/gif";
5 | public static final String TRACKING_GIF = GIF;
6 | public static final String JPEG = "image/jpeg";
7 |
8 | public static final String JAVA_SCRIPT = "application/javascript; charset=utf-8";
9 | public static final String XML = "application/xml; charset=utf-8";
10 | public static final String JSON = "application/json; charset=utf-8";
11 |
12 | public static final String TEXT_UTF8 = "text/plain; charset=UTF-8";
13 | public static final String HTML_UTF8 = "text/html; charset=UTF-8";
14 | }
15 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/http/HttpOutputResource.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class HttpOutputResource {
6 | ByteBuf byteBuf;
7 | long length;
8 | long lastModified;
9 |
10 |
11 | public HttpOutputResource(ByteBuf byteBuf, long lastModified) {
12 | super();
13 | this.byteBuf = byteBuf;
14 | this.length = byteBuf.readableBytes();
15 | this.lastModified = lastModified;
16 | }
17 |
18 | public ByteBuf getByteBuf() {
19 | return byteBuf;
20 | }
21 |
22 | public void setByteBuf(ByteBuf byteBuf) {
23 | this.byteBuf = byteBuf;
24 | }
25 |
26 | public long getLength() {
27 | return length;
28 | }
29 |
30 | public void setLength(long length) {
31 | this.length = length;
32 | }
33 |
34 | public long getLastModified() {
35 | return lastModified;
36 | }
37 |
38 | public void setLastModified(long lastModified) {
39 | this.lastModified = lastModified;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/redis/RedisCommand.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import netty.cookbook.common.StringPool;
4 | import redis.clients.jedis.Jedis;
5 | import redis.clients.jedis.ShardedJedis;
6 | import redis.clients.jedis.ShardedJedisPool;
7 | import redis.clients.jedis.exceptions.JedisException;
8 |
9 | public abstract class RedisCommand {
10 | protected ShardedJedisPool jedisPool;
11 | protected ShardedJedis shardedJedis = null;
12 | protected Jedis jedis = null;
13 |
14 | public RedisCommand(ShardedJedisPool jedisPool) {
15 | super();
16 | if (jedisPool == null) {
17 | throw new IllegalArgumentException("jedisPool is NULL!");
18 | }
19 | this.jedisPool = jedisPool;
20 | }
21 |
22 | public T execute() {
23 | boolean commited = false;
24 | T rs = null;
25 | try {
26 | shardedJedis = jedisPool.getResource();
27 | if (shardedJedis != null) {
28 | jedis = shardedJedis.getShard(StringPool.BLANK);
29 | rs = build();
30 | commited = true;
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | } finally {
35 | freeRedisResource(jedisPool, shardedJedis, commited);
36 | }
37 | return rs;
38 | }
39 |
40 | public static void freeRedisResource(ShardedJedisPool jedisPool, ShardedJedis shardedJedis, boolean isCommited){
41 | if (shardedJedis != null && jedisPool != null) {
42 | if (isCommited) {
43 | jedisPool.returnResource(shardedJedis);
44 | } else {
45 | jedisPool.returnBrokenResource(shardedJedis);
46 | }
47 | }
48 | }
49 |
50 | //define the logic at implementer
51 | protected abstract T build() throws JedisException;
52 | }
--------------------------------------------------------------------------------
/chapter6/src/main/java/netty/cookbook/common/redis/RedisInfo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import redis.clients.jedis.JedisShardInfo;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | public class RedisInfo {
10 | public static final String LOCALHOST_STR = "localhost";
11 |
12 | private String host;
13 | private int port;
14 | private String auth;
15 | private ShardedJedisPool shardedJedisPool;
16 |
17 | protected void initThePool(){
18 | List shardInfos = new ArrayList(1);
19 | shardInfos.add(new JedisShardInfo(getHost(), getPort(), 0));
20 | shardedJedisPool = new ShardedJedisPool(RedisConnectionPoolConfig.getJedisPoolConfigInstance(), shardInfos);
21 | }
22 |
23 | public RedisInfo(String host, int port) {
24 | this.host = host;
25 | this.port = port;
26 | initThePool();
27 | }
28 |
29 | public RedisInfo(String host, int port,String auth) {
30 | this.host = host;
31 | this.port = port;
32 | this.auth = auth;
33 | initThePool();
34 | }
35 |
36 | public String getHost() {
37 | return host;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public String getAuth() {
45 | return auth;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (obj instanceof RedisInfo) {
51 | RedisInfo hp = (RedisInfo) obj;
52 |
53 | String thisHost = convertHost(host);
54 | String hpHost = convertHost(hp.host);
55 | return port == hp.port && thisHost.equals(hpHost);
56 |
57 | }
58 |
59 | return false;
60 | }
61 |
62 | public ShardedJedisPool getShardedJedisPool() {
63 | return shardedJedisPool;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return host + ":" + port;
69 | }
70 |
71 | private String convertHost(String host) {
72 | if (host.equals("127.0.0.1"))
73 | return LOCALHOST_STR;
74 | else if (host.equals("::1"))
75 | return LOCALHOST_STR;
76 |
77 | return host;
78 | }
79 | }
--------------------------------------------------------------------------------
/chapter7/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter7/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | chapter7
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter7/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | Netty Cookbook - code for chapter 7: High performance Web with HTTP/2
4 |
5 | https://http2.github.io
6 | http://en.wikipedia.org/wiki/HTTP/2
7 |
8 | * Recipe 7.1 Using codec-http2 to improve the speed of Web
9 | * Recipe 7.2 Enabling multiple streams in single connection
10 | * Recipe 7.3 Setting priority in requests
11 | * Recipe 7.4 Compressing data response
12 | * Recipe 7.5 Enabling server push
13 | * Recipe 7.6 Building better static file server for high concurrency
14 |
--------------------------------------------------------------------------------
/chapter7/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 |
4 | sourceCompatibility = 1.8
5 |
6 | version = '1.0'
7 |
8 | repositories {
9 | mavenCentral()
10 | maven {
11 | url "http://clinker.netty.io/nexus/content/repositories/snapshots/"
12 | }
13 | }
14 |
15 | dependencies {
16 | compile (
17 | // common
18 | 'io.netty:netty-all:5.0.0.Alpha2-SNAPSHOT'
19 | ,'com.twitter:hpack:0.10.0'
20 |
21 | ,'commons-io:commons-io:2.4'
22 | ,'org.apache.commons:commons-lang3:3.3.2'
23 | ,'log4j:log4j:1.2.17'
24 | ,'org.slf4j:slf4j-log4j12:1.7.7'
25 | ,'org.yaml:snakeyaml:1.14'
26 |
27 | ,'com.google.code.gson:gson:2.3'
28 | ,'com.google.guava:guava:18.0'
29 | ,'org.twitter4j:twitter4j-core:4.0.2'
30 | ,'org.twitter4j:twitter4j-stream:4.0.2'
31 | ,'redis.clients:jedis:2.6.2'
32 | ,'com.github.jknack:handlebars:2.0.0'
33 |
34 | )
35 | testCompile group: 'junit', name: 'junit', version: '4.11'
36 | }
37 |
--------------------------------------------------------------------------------
/chapter7/src/main/java/chapter7/recipe1/client/Http2SettingsHandler.java:
--------------------------------------------------------------------------------
1 | package chapter7.recipe1.client;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelPromise;
5 | import io.netty.channel.SimpleChannelInboundHandler;
6 | import io.netty.handler.codec.http2.Http2Settings;
7 |
8 | import java.util.concurrent.TimeUnit;
9 |
10 | /**
11 | * Reads the first {@link Http2Settings} object and notifies a {@link ChannelPromise}
12 | */
13 | public class Http2SettingsHandler extends SimpleChannelInboundHandler {
14 | private ChannelPromise promise;
15 |
16 | /**
17 | * Create new instance
18 | *
19 | * @param promise Promise object used to notify when first settings are received
20 | */
21 | public Http2SettingsHandler(ChannelPromise promise) {
22 | this.promise = promise;
23 | }
24 |
25 | /**
26 | * Wait for this handler to be added after the upgrade to HTTP/2, and for initial preface
27 | * handshake to complete.
28 | *
29 | * @param timeout Time to wait
30 | * @param unit {@link TimeUnit} for {@code timeout}
31 | * @throws Exception if timeout or other failure occurs
32 | */
33 | public void awaitSettings(long timeout, TimeUnit unit) throws Exception {
34 | if (!promise.awaitUninterruptibly(timeout, unit)) {
35 | throw new IllegalStateException("Timed out waiting for settings");
36 | }
37 | if (!promise.isSuccess()) {
38 | throw new RuntimeException(promise.cause());
39 | }
40 | }
41 |
42 | @Override
43 | protected void messageReceived(ChannelHandlerContext ctx, Http2Settings msg) throws Exception {
44 | promise.setSuccess();
45 |
46 | // Only care about the first settings message
47 | ctx.pipeline().remove(this);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/chapter7/src/main/java/chapter7/recipe1/server/Http2OrHttpHandler.java:
--------------------------------------------------------------------------------
1 | package chapter7.recipe1.server;
2 |
3 | import io.netty.channel.ChannelHandler;
4 | import io.netty.handler.codec.http2.Http2ConnectionHandler;
5 | import io.netty.handler.codec.http2.Http2OrHttpChooser;
6 |
7 | import javax.net.ssl.SSLEngine;
8 |
9 | /**
10 | * Negotiates with the browser if HTTP2 or HTTP is going to be used. Once decided, the Netty
11 | * pipeline is setup with the correct handlers for the selected protocol.
12 | */
13 | public class Http2OrHttpHandler extends Http2OrHttpChooser {
14 | private static final int MAX_CONTENT_LENGTH = 1024 * 100;
15 |
16 | public Http2OrHttpHandler() {
17 | this(MAX_CONTENT_LENGTH);
18 | }
19 |
20 | public Http2OrHttpHandler(int maxHttpContentLength) {
21 | super(maxHttpContentLength);
22 | }
23 |
24 | @Override
25 | protected SelectedProtocol getProtocol(SSLEngine engine) {
26 | String[] protocol = engine.getSession().getProtocol().split(":");
27 | if (protocol != null && protocol.length > 1) {
28 | SelectedProtocol selectedProtocol = SelectedProtocol.protocol(protocol[1]);
29 | System.err.println("Selected Protocol is " + selectedProtocol);
30 | return selectedProtocol;
31 | }
32 | return SelectedProtocol.UNKNOWN;
33 | }
34 |
35 | @Override
36 | protected ChannelHandler createHttp1RequestHandler() {
37 | return new HelloWorldHttp1Handler();
38 | }
39 |
40 | @Override
41 | protected Http2ConnectionHandler createHttp2RequestHandler() {
42 | return new HelloWorldHttp2Handler();
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/chapter7/src/main/java/chapter7/recipe1/server/Http2Server.java:
--------------------------------------------------------------------------------
1 | package chapter7.recipe1.server;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.Channel;
5 | import io.netty.channel.ChannelOption;
6 | import io.netty.channel.EventLoopGroup;
7 | import io.netty.channel.nio.NioEventLoopGroup;
8 | import io.netty.channel.socket.nio.NioServerSocketChannel;
9 | import io.netty.handler.logging.LogLevel;
10 | import io.netty.handler.logging.LoggingHandler;
11 |
12 | /**
13 | * @author Trieu
14 | * @since Feb 23, 2015
15 | */
16 | public class Http2Server {
17 |
18 | static final boolean SSL = System.getProperty("ssl") != null;
19 | static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
20 |
21 | public static void main(String[] args) throws Exception {
22 |
23 | // Configure the server.
24 | EventLoopGroup bossGroup = new NioEventLoopGroup(1);
25 | EventLoopGroup workerGroup = new NioEventLoopGroup();
26 | try {
27 | ServerBootstrap b = new ServerBootstrap();
28 | b.option(ChannelOption.SO_BACKLOG, 1024);
29 | b.group(bossGroup, workerGroup)
30 | .channel(NioServerSocketChannel.class)
31 | .handler(new LoggingHandler(LogLevel.INFO))
32 | .childHandler(new Http2ServerInitializer());
33 |
34 | Channel ch = b.bind(PORT).sync().channel();
35 |
36 | System.err.println("Open your HTTP/2-enabled web browser and navigate to " +
37 | (SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/');
38 |
39 | ch.closeFuture().sync();
40 | } finally {
41 | bossGroup.shutdownGracefully();
42 | workerGroup.shutdownGracefully();
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/chapter7/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter7/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter7/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter7/src/main/java/netty/cookbook/common/Http2Util.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class Http2Util {
4 | /**
5 | * Response header sent in response to the http->http2 cleartext upgrade request.
6 | */
7 | public static final String UPGRADE_RESPONSE_HEADER = "Http-To-Http2-Upgrade";
8 | }
9 |
--------------------------------------------------------------------------------
/chapter7/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter7/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter7/src/main/java/netty/cookbook/common/redis/RedisCommand.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import netty.cookbook.common.StringPool;
4 | import redis.clients.jedis.Jedis;
5 | import redis.clients.jedis.ShardedJedis;
6 | import redis.clients.jedis.ShardedJedisPool;
7 | import redis.clients.jedis.exceptions.JedisException;
8 |
9 | public abstract class RedisCommand {
10 | protected ShardedJedisPool jedisPool;
11 | protected ShardedJedis shardedJedis = null;
12 | protected Jedis jedis = null;
13 |
14 | public RedisCommand(ShardedJedisPool jedisPool) {
15 | super();
16 | if (jedisPool == null) {
17 | throw new IllegalArgumentException("jedisPool is NULL!");
18 | }
19 | this.jedisPool = jedisPool;
20 | }
21 |
22 | public T execute() {
23 | boolean commited = false;
24 | T rs = null;
25 | try {
26 | shardedJedis = jedisPool.getResource();
27 | if (shardedJedis != null) {
28 | jedis = shardedJedis.getShard(StringPool.BLANK);
29 | rs = build();
30 | commited = true;
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | } finally {
35 | freeRedisResource(jedisPool, shardedJedis, commited);
36 | }
37 | return rs;
38 | }
39 |
40 | public static void freeRedisResource(ShardedJedisPool jedisPool, ShardedJedis shardedJedis, boolean isCommited){
41 | if (shardedJedis != null && jedisPool != null) {
42 | if (isCommited) {
43 | jedisPool.returnResource(shardedJedis);
44 | } else {
45 | jedisPool.returnBrokenResource(shardedJedis);
46 | }
47 | }
48 | }
49 |
50 | //define the logic at implementer
51 | protected abstract T build() throws JedisException;
52 | }
--------------------------------------------------------------------------------
/chapter7/src/main/java/netty/cookbook/common/redis/RedisInfo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import redis.clients.jedis.JedisShardInfo;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | public class RedisInfo {
10 | public static final String LOCALHOST_STR = "localhost";
11 |
12 | private String host;
13 | private int port;
14 | private String auth;
15 | private ShardedJedisPool shardedJedisPool;
16 |
17 | protected void initThePool(){
18 | List shardInfos = new ArrayList(1);
19 | shardInfos.add(new JedisShardInfo(getHost(), getPort(), 0));
20 | shardedJedisPool = new ShardedJedisPool(RedisConnectionPoolConfig.getJedisPoolConfigInstance(), shardInfos);
21 | }
22 |
23 | public RedisInfo(String host, int port) {
24 | this.host = host;
25 | this.port = port;
26 | initThePool();
27 | }
28 |
29 | public RedisInfo(String host, int port,String auth) {
30 | this.host = host;
31 | this.port = port;
32 | this.auth = auth;
33 | initThePool();
34 | }
35 |
36 | public String getHost() {
37 | return host;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public String getAuth() {
45 | return auth;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (obj instanceof RedisInfo) {
51 | RedisInfo hp = (RedisInfo) obj;
52 |
53 | String thisHost = convertHost(host);
54 | String hpHost = convertHost(hp.host);
55 | return port == hp.port && thisHost.equals(hpHost);
56 |
57 | }
58 |
59 | return false;
60 | }
61 |
62 | public ShardedJedisPool getShardedJedisPool() {
63 | return shardedJedisPool;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return host + ":" + port;
69 | }
70 |
71 | private String convertHost(String host) {
72 | if (host.equals("127.0.0.1"))
73 | return LOCALHOST_STR;
74 | else if (host.equals("::1"))
75 | return LOCALHOST_STR;
76 |
77 | return host;
78 | }
79 | }
--------------------------------------------------------------------------------
/chapter8/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter8/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | chapter5
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter8/README.md:
--------------------------------------------------------------------------------
1 | Netty Cookbook - chapter 8 code
--------------------------------------------------------------------------------
/chapter8/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 |
4 | sourceCompatibility = 1.8
5 |
6 | version = '1.0'
7 |
8 | repositories {
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | compile (
14 | // common
15 | 'io.netty:netty-all:4.0.25.Final'
16 | ,'commons-io:commons-io:2.4'
17 | ,'org.apache.commons:commons-lang3:3.3.2'
18 | ,'log4j:log4j:1.2.17'
19 | ,'org.slf4j:slf4j-log4j12:1.7.7'
20 | ,'org.yaml:snakeyaml:1.14'
21 |
22 | ,'com.google.code.gson:gson:2.3'
23 | ,'com.google.guava:guava:18.0'
24 | ,'org.twitter4j:twitter4j-core:4.0.2'
25 | ,'org.twitter4j:twitter4j-stream:4.0.2'
26 | ,'redis.clients:jedis:2.6.2'
27 | ,'com.github.jknack:handlebars:2.0.0'
28 |
29 | )
30 | testCompile group: 'junit', name: 'junit', version: '4.11'
31 | }
32 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/chapter4/recipe1/WebSocketServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe1;
2 |
3 |
4 | /**
5 | * @author toddf
6 | * @since June 29, 2012
7 | */
8 | public class WebSocketServer {
9 |
10 |
11 | public static void main(String[] args) {
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter8/src/main/java/chapter4/recipe2/RealtimeWebSocketIO.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe2;
2 |
3 | public class RealtimeWebSocketIO {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/chapter4/recipe3/ChatServerWithSTOMP.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe3;
2 |
3 | public class ChatServerWithSTOMP {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/chapter4/recipe4/RealtimeWidgetServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe4;
2 |
3 | public class RealtimeWidgetServer {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/http/ContentTypePool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | public class ContentTypePool {
4 | public static final String GIF = "image/gif";
5 | public static final String TRACKING_GIF = GIF;
6 | public static final String JPEG = "image/jpeg";
7 |
8 | public static final String JAVA_SCRIPT = "application/javascript; charset=utf-8";
9 | public static final String XML = "application/xml; charset=utf-8";
10 | public static final String JSON = "application/json; charset=utf-8";
11 |
12 | public static final String TEXT_UTF8 = "text/plain; charset=UTF-8";
13 | public static final String HTML_UTF8 = "text/html; charset=UTF-8";
14 | }
15 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/http/HttpOutputResource.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class HttpOutputResource {
6 | ByteBuf byteBuf;
7 | long length;
8 | long lastModified;
9 |
10 |
11 | public HttpOutputResource(ByteBuf byteBuf, long lastModified) {
12 | super();
13 | this.byteBuf = byteBuf;
14 | this.length = byteBuf.readableBytes();
15 | this.lastModified = lastModified;
16 | }
17 |
18 | public ByteBuf getByteBuf() {
19 | return byteBuf;
20 | }
21 |
22 | public void setByteBuf(ByteBuf byteBuf) {
23 | this.byteBuf = byteBuf;
24 | }
25 |
26 | public long getLength() {
27 | return length;
28 | }
29 |
30 | public void setLength(long length) {
31 | this.length = length;
32 | }
33 |
34 | public long getLastModified() {
35 | return lastModified;
36 | }
37 |
38 | public void setLastModified(long lastModified) {
39 | this.lastModified = lastModified;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/redis/RedisCommand.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import netty.cookbook.common.StringPool;
4 | import redis.clients.jedis.Jedis;
5 | import redis.clients.jedis.ShardedJedis;
6 | import redis.clients.jedis.ShardedJedisPool;
7 | import redis.clients.jedis.exceptions.JedisException;
8 |
9 | public abstract class RedisCommand {
10 | protected ShardedJedisPool jedisPool;
11 | protected ShardedJedis shardedJedis = null;
12 | protected Jedis jedis = null;
13 |
14 | public RedisCommand(ShardedJedisPool jedisPool) {
15 | super();
16 | if (jedisPool == null) {
17 | throw new IllegalArgumentException("jedisPool is NULL!");
18 | }
19 | this.jedisPool = jedisPool;
20 | }
21 |
22 | public T execute() {
23 | boolean commited = false;
24 | T rs = null;
25 | try {
26 | shardedJedis = jedisPool.getResource();
27 | if (shardedJedis != null) {
28 | jedis = shardedJedis.getShard(StringPool.BLANK);
29 | rs = build();
30 | commited = true;
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | } finally {
35 | freeRedisResource(jedisPool, shardedJedis, commited);
36 | }
37 | return rs;
38 | }
39 |
40 | public static void freeRedisResource(ShardedJedisPool jedisPool, ShardedJedis shardedJedis, boolean isCommited){
41 | if (shardedJedis != null && jedisPool != null) {
42 | if (isCommited) {
43 | jedisPool.returnResource(shardedJedis);
44 | } else {
45 | jedisPool.returnBrokenResource(shardedJedis);
46 | }
47 | }
48 | }
49 |
50 | //define the logic at implementer
51 | protected abstract T build() throws JedisException;
52 | }
--------------------------------------------------------------------------------
/chapter8/src/main/java/netty/cookbook/common/redis/RedisInfo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import redis.clients.jedis.JedisShardInfo;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | public class RedisInfo {
10 | public static final String LOCALHOST_STR = "localhost";
11 |
12 | private String host;
13 | private int port;
14 | private String auth;
15 | private ShardedJedisPool shardedJedisPool;
16 |
17 | protected void initThePool(){
18 | List shardInfos = new ArrayList(1);
19 | shardInfos.add(new JedisShardInfo(getHost(), getPort(), 0));
20 | shardedJedisPool = new ShardedJedisPool(RedisConnectionPoolConfig.getJedisPoolConfigInstance(), shardInfos);
21 | }
22 |
23 | public RedisInfo(String host, int port) {
24 | this.host = host;
25 | this.port = port;
26 | initThePool();
27 | }
28 |
29 | public RedisInfo(String host, int port,String auth) {
30 | this.host = host;
31 | this.port = port;
32 | this.auth = auth;
33 | initThePool();
34 | }
35 |
36 | public String getHost() {
37 | return host;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public String getAuth() {
45 | return auth;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (obj instanceof RedisInfo) {
51 | RedisInfo hp = (RedisInfo) obj;
52 |
53 | String thisHost = convertHost(host);
54 | String hpHost = convertHost(hp.host);
55 | return port == hp.port && thisHost.equals(hpHost);
56 |
57 | }
58 |
59 | return false;
60 | }
61 |
62 | public ShardedJedisPool getShardedJedisPool() {
63 | return shardedJedisPool;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return host + ":" + port;
69 | }
70 |
71 | private String convertHost(String host) {
72 | if (host.equals("127.0.0.1"))
73 | return LOCALHOST_STR;
74 | else if (host.equals("::1"))
75 | return LOCALHOST_STR;
76 |
77 | return host;
78 | }
79 | }
--------------------------------------------------------------------------------
/chapter9/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/chapter9/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | chapter5
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chapter9/README.md:
--------------------------------------------------------------------------------
1 | Netty Cookbook - chapter 9 code
--------------------------------------------------------------------------------
/chapter9/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 |
4 | sourceCompatibility = 1.8
5 |
6 | version = '1.0'
7 |
8 | repositories {
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | compile (
14 | // common
15 | 'io.netty:netty-all:4.0.25.Final'
16 | ,'commons-io:commons-io:2.4'
17 | ,'org.apache.commons:commons-lang3:3.3.2'
18 | ,'log4j:log4j:1.2.17'
19 | ,'org.slf4j:slf4j-log4j12:1.7.7'
20 | ,'org.yaml:snakeyaml:1.14'
21 |
22 | ,'com.google.code.gson:gson:2.3'
23 | ,'com.google.guava:guava:18.0'
24 | ,'org.twitter4j:twitter4j-core:4.0.2'
25 | ,'org.twitter4j:twitter4j-stream:4.0.2'
26 | ,'redis.clients:jedis:2.6.2'
27 | ,'com.github.jknack:handlebars:2.0.0'
28 |
29 | )
30 | testCompile group: 'junit', name: 'junit', version: '4.11'
31 | }
32 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/chapter4/recipe1/WebSocketServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe1;
2 |
3 |
4 | /**
5 | * @author toddf
6 | * @since June 29, 2012
7 | */
8 | public class WebSocketServer {
9 |
10 |
11 | public static void main(String[] args) {
12 | }
13 | }
--------------------------------------------------------------------------------
/chapter9/src/main/java/chapter4/recipe2/RealtimeWebSocketIO.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe2;
2 |
3 | public class RealtimeWebSocketIO {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/chapter4/recipe3/ChatServerWithSTOMP.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe3;
2 |
3 | public class ChatServerWithSTOMP {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/chapter4/recipe4/RealtimeWidgetServer.java:
--------------------------------------------------------------------------------
1 | package chapter4.recipe4;
2 |
3 | public class RealtimeWidgetServer {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/CharPool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class CharPool {
4 |
5 | public static final char AMPERSAND = '&';
6 |
7 | public static final char APOSTROPHE = '\'';
8 |
9 | public static final char AT = '@';
10 |
11 | public static final char BACK_SLASH = '\\';
12 |
13 | public static final char CLOSE_BRACKET = ']';
14 |
15 | public static final char CLOSE_CURLY_BRACE = '}';
16 |
17 | public static final char CLOSE_PARENTHESIS = ')';
18 |
19 | public static final char COLON = ':';
20 |
21 | public static final char COMMA = ',';
22 |
23 | public static final char DASH = '-';
24 |
25 | public static final char EQUAL = '=';
26 |
27 | public static final char GREATER_THAN = '>';
28 |
29 | public static final char FORWARD_SLASH = '/';
30 |
31 | public static final char LESS_THAN = '<';
32 |
33 | public static final char LOWER_CASE_E = 'e';
34 |
35 | public static final char MINUS = '-';
36 |
37 | public static final char NEW_LINE = '\n';
38 |
39 | public static final char OPEN_BRACKET = '[';
40 |
41 | public static final char OPEN_CURLY_BRACE = '{';
42 |
43 | public static final char OPEN_PARENTHESIS = '(';
44 |
45 | public static final char PERCENT = '%';
46 |
47 | public static final char PERIOD = '.';
48 |
49 | public static final char PIPE = '|';
50 |
51 | public static final char PLUS = '+';
52 |
53 | public static final char POUND = '#';
54 |
55 | public static final char QUESTION = '?';
56 |
57 | public static final char QUOTE = '\"';
58 |
59 | public static final char RETURN = '\r';
60 |
61 | public static final char SEMICOLON = ';';
62 |
63 | public static final char SLASH = FORWARD_SLASH;
64 |
65 | public static final char SPACE = ' ';
66 |
67 | public static final char STAR = '*';
68 |
69 | public static final char TILDE = '~';
70 |
71 | public static final char UNDERLINE = '_';
72 |
73 | public static final char UPPER_CASE_E = 'E';
74 |
75 | public static final char TAB = '\t';
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/http/ContentTypePool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | public class ContentTypePool {
4 | public static final String GIF = "image/gif";
5 | public static final String TRACKING_GIF = GIF;
6 | public static final String JPEG = "image/jpeg";
7 |
8 | public static final String JAVA_SCRIPT = "application/javascript; charset=utf-8";
9 | public static final String XML = "application/xml; charset=utf-8";
10 | public static final String JSON = "application/json; charset=utf-8";
11 |
12 | public static final String TEXT_UTF8 = "text/plain; charset=UTF-8";
13 | public static final String HTML_UTF8 = "text/html; charset=UTF-8";
14 | }
15 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/http/HttpOutputResource.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class HttpOutputResource {
6 | ByteBuf byteBuf;
7 | long length;
8 | long lastModified;
9 |
10 |
11 | public HttpOutputResource(ByteBuf byteBuf, long lastModified) {
12 | super();
13 | this.byteBuf = byteBuf;
14 | this.length = byteBuf.readableBytes();
15 | this.lastModified = lastModified;
16 | }
17 |
18 | public ByteBuf getByteBuf() {
19 | return byteBuf;
20 | }
21 |
22 | public void setByteBuf(ByteBuf byteBuf) {
23 | this.byteBuf = byteBuf;
24 | }
25 |
26 | public long getLength() {
27 | return length;
28 | }
29 |
30 | public void setLength(long length) {
31 | this.length = length;
32 | }
33 |
34 | public long getLastModified() {
35 | return lastModified;
36 | }
37 |
38 | public void setLastModified(long lastModified) {
39 | this.lastModified = lastModified;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/redis/RedisCommand.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import netty.cookbook.common.StringPool;
4 | import redis.clients.jedis.Jedis;
5 | import redis.clients.jedis.ShardedJedis;
6 | import redis.clients.jedis.ShardedJedisPool;
7 | import redis.clients.jedis.exceptions.JedisException;
8 |
9 | public abstract class RedisCommand {
10 | protected ShardedJedisPool jedisPool;
11 | protected ShardedJedis shardedJedis = null;
12 | protected Jedis jedis = null;
13 |
14 | public RedisCommand(ShardedJedisPool jedisPool) {
15 | super();
16 | if (jedisPool == null) {
17 | throw new IllegalArgumentException("jedisPool is NULL!");
18 | }
19 | this.jedisPool = jedisPool;
20 | }
21 |
22 | public T execute() {
23 | boolean commited = false;
24 | T rs = null;
25 | try {
26 | shardedJedis = jedisPool.getResource();
27 | if (shardedJedis != null) {
28 | jedis = shardedJedis.getShard(StringPool.BLANK);
29 | rs = build();
30 | commited = true;
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | } finally {
35 | freeRedisResource(jedisPool, shardedJedis, commited);
36 | }
37 | return rs;
38 | }
39 |
40 | public static void freeRedisResource(ShardedJedisPool jedisPool, ShardedJedis shardedJedis, boolean isCommited){
41 | if (shardedJedis != null && jedisPool != null) {
42 | if (isCommited) {
43 | jedisPool.returnResource(shardedJedis);
44 | } else {
45 | jedisPool.returnBrokenResource(shardedJedis);
46 | }
47 | }
48 | }
49 |
50 | //define the logic at implementer
51 | protected abstract T build() throws JedisException;
52 | }
--------------------------------------------------------------------------------
/chapter9/src/main/java/netty/cookbook/common/redis/RedisInfo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import redis.clients.jedis.JedisShardInfo;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | public class RedisInfo {
10 | public static final String LOCALHOST_STR = "localhost";
11 |
12 | private String host;
13 | private int port;
14 | private String auth;
15 | private ShardedJedisPool shardedJedisPool;
16 |
17 | protected void initThePool(){
18 | List shardInfos = new ArrayList(1);
19 | shardInfos.add(new JedisShardInfo(getHost(), getPort(), 0));
20 | shardedJedisPool = new ShardedJedisPool(RedisConnectionPoolConfig.getJedisPoolConfigInstance(), shardInfos);
21 | }
22 |
23 | public RedisInfo(String host, int port) {
24 | this.host = host;
25 | this.port = port;
26 | initThePool();
27 | }
28 |
29 | public RedisInfo(String host, int port,String auth) {
30 | this.host = host;
31 | this.port = port;
32 | this.auth = auth;
33 | initThePool();
34 | }
35 |
36 | public String getHost() {
37 | return host;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public String getAuth() {
45 | return auth;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (obj instanceof RedisInfo) {
51 | RedisInfo hp = (RedisInfo) obj;
52 |
53 | String thisHost = convertHost(host);
54 | String hpHost = convertHost(hp.host);
55 | return port == hp.port && thisHost.equals(hpHost);
56 |
57 | }
58 |
59 | return false;
60 | }
61 |
62 | public ShardedJedisPool getShardedJedisPool() {
63 | return shardedJedisPool;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return host + ":" + port;
69 | }
70 |
71 | private String convertHost(String host) {
72 | if (host.equals("127.0.0.1"))
73 | return LOCALHOST_STR;
74 | else if (host.equals("::1"))
75 | return LOCALHOST_STR;
76 |
77 | return host;
78 | }
79 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /build/
3 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | netty-cookbook-java-src
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.springsource.ide.eclipse.gradle.core.nature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/README.txt:
--------------------------------------------------------------------------------
1 | demo asynch programming with traditional blocking IO
--------------------------------------------------------------------------------
/netty-cookbook-java-src/configs/redis-connection-pool-configs.json:
--------------------------------------------------------------------------------
1 | {
2 | maxTotal : 3000,
3 | maxIdle : 20,
4 | minIdle : 2,
5 | maxWaitMillis : 5000;
6 | numTestsPerEvictionRun : 10,
7 | testOnBorrow : true,
8 | testOnReturn : true,
9 | testWhileIdle : true,
10 | timeBetweenEvictionRunsMillis : 60000
11 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/data/text-file.txt:
--------------------------------------------------------------------------------
1 | This is a message in text-file.txt
--------------------------------------------------------------------------------
/netty-cookbook-java-src/lib/mongodb-async-driver-2.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/netty-cookbook-java-src/lib/mongodb-async-driver-2.0.1.jar
--------------------------------------------------------------------------------
/netty-cookbook-java-src/lib/netty-codec-ftp-0.2-SNAPSHOT.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/netty-cookbook-java-src/lib/netty-codec-ftp-0.2-SNAPSHOT.jar
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/avro/mail.avpr:
--------------------------------------------------------------------------------
1 | {"namespace": "avro",
2 | "protocol": "Mail",
3 |
4 | "types": [
5 | {"name": "Message", "type": "record",
6 | "fields": [
7 | {"name": "to", "type": "string"},
8 | {"name": "from", "type": "string"},
9 | {"name": "body", "type": "string"}
10 | ]
11 | }
12 | ],
13 |
14 | "messages": {
15 | "send": {
16 | "request": [{"name": "message", "type": "Message"}],
17 | "response": "string"
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/avro/Mail.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Autogenerated by Avro
3 | *
4 | * DO NOT EDIT DIRECTLY
5 | */
6 | package avro;
7 |
8 | @SuppressWarnings("all")
9 | @org.apache.avro.specific.AvroGenerated
10 | public interface Mail {
11 | public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"Mail\",\"namespace\":\"avro\",\"types\":[{\"type\":\"record\",\"name\":\"Message\",\"fields\":[{\"name\":\"to\",\"type\":\"string\"},{\"name\":\"from\",\"type\":\"string\"},{\"name\":\"body\",\"type\":\"string\"}]}],\"messages\":{\"send\":{\"request\":[{\"name\":\"message\",\"type\":\"Message\"}],\"response\":\"string\"}}}");
12 | java.lang.CharSequence send(avro.Message message) throws org.apache.avro.AvroRemoteException;
13 |
14 | @SuppressWarnings("all")
15 | public interface Callback extends Mail {
16 | public static final org.apache.avro.Protocol PROTOCOL = avro.Mail.PROTOCOL;
17 | void send(avro.Message message, org.apache.avro.ipc.Callback callback) throws java.io.IOException;
18 | }
19 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=INFO, stdout
3 |
4 | # Redirect log messages to console
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
9 |
10 | # Redirect log messages to a log file, support file rolling.
11 | log4j.appender.file=org.apache.log4j.RollingFileAppender
12 | log4j.appender.file.File=./log/java-cookbook-demo
13 | log4j.appender.file.MaxFileSize=5MB
14 | log4j.appender.file.MaxBackupIndex=10
15 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter1/recipe4/TcpServerInboundHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter1.recipe4;
2 |
3 | import io.netty.channel.ChannelHandler.Sharable;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 | import io.netty.util.ReferenceCountUtil;
7 |
8 | /**
9 | * Handler implementation for the TCP server.
10 | */
11 | @Sharable
12 | public class TcpServerInboundHandler extends ChannelInboundHandlerAdapter {
13 |
14 |
15 | @Override
16 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
17 | try {
18 | System.out.println("TcpServerInboundHandler");
19 | StringBuilder s = new StringBuilder();
20 | s.append("Ok TCP client, TcpServerInboundHandler got your message \"").append(msg).append("\"");
21 | ctx.write(s);
22 | } finally {
23 | ReferenceCountUtil.release(msg);
24 | }
25 | }
26 |
27 | @Override
28 | public void channelReadComplete(ChannelHandlerContext ctx) {
29 | ctx.flush();
30 | }
31 |
32 | @Override
33 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
34 | // Close the connection when an exception is raised.
35 | cause.printStackTrace();
36 | ctx.close();
37 | }
38 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter1/recipe4/TcpServerOutboundHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter1.recipe4;
2 |
3 | import io.netty.channel.ChannelHandler.Sharable;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelOutboundHandlerAdapter;
6 | import io.netty.util.concurrent.Future;
7 | import io.netty.util.concurrent.GenericFutureListener;
8 |
9 | /**
10 | * Handler implementation for the TCP server.
11 | */
12 | @Sharable
13 | public class TcpServerOutboundHandler extends ChannelOutboundHandlerAdapter {
14 | @Override
15 | public void flush(ChannelHandlerContext ctx) throws Exception {
16 | super.flush(ctx);
17 | ctx.close().addListener(new GenericFutureListener>() {
18 | @Override
19 | public void operationComplete(Future super Void> future)
20 | throws Exception {
21 | System.out.println("close connection: "+future.isSuccess());
22 | }
23 | });
24 | }
25 |
26 | @Override
27 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
28 | // Close the connection when an exception is raised.
29 | cause.printStackTrace();
30 | ctx.close();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter1/recipe6/DataPipelineProcessingServer.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter1.recipe6;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.Channel;
5 | import io.netty.channel.ChannelFuture;
6 | import io.netty.channel.ChannelOption;
7 | import io.netty.channel.EventLoopGroup;
8 | import io.netty.channel.nio.NioEventLoopGroup;
9 | import io.netty.channel.socket.nio.NioServerSocketChannel;
10 | import io.netty.handler.logging.LogLevel;
11 | import io.netty.handler.logging.LoggingHandler;
12 |
13 | public class DataPipelineProcessingServer {
14 | static final int PORT = 8007;
15 |
16 | public static void main(String[] args) throws Exception{
17 | // Configure the server.
18 | EventLoopGroup bossGroup = new NioEventLoopGroup(1);
19 | EventLoopGroup workerGroup = new NioEventLoopGroup();
20 | try {
21 | ServerBootstrap b = new ServerBootstrap();
22 | b.group(bossGroup, workerGroup)
23 | .channel(NioServerSocketChannel.class)
24 | .option(ChannelOption.SO_BACKLOG, 100)
25 | .handler(new LoggingHandler(LogLevel.INFO))
26 | .childHandler(new DataProcessingPipeline());
27 |
28 | // Start the server.
29 | ChannelFuture f = b.bind(PORT).sync();
30 | Channel channel = f.channel();
31 |
32 | // Wait until the server socket is closed.
33 | channel.closeFuture().sync();
34 | } finally {
35 | // Shut down all event loops to terminate all threads.
36 | bossGroup.shutdownGracefully();
37 | workerGroup.shutdownGracefully();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe10/ClientAvroRPC.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe10;
2 |
3 |
4 | import java.io.IOException;
5 | import java.net.InetSocketAddress;
6 |
7 | import netty.cookbook.common.LogUtil;
8 |
9 | import org.apache.avro.ipc.NettyTransceiver;
10 | import org.apache.avro.ipc.specific.SpecificRequestor;
11 | import org.apache.avro.util.Utf8;
12 |
13 | import avro.Mail;
14 | import avro.Message;
15 |
16 | /**
17 | * Start ClientAvroRPC, and send a message.
18 | */
19 | public class ClientAvroRPC {
20 | public static void main(String[] args) throws IOException {
21 | if(args.length < 3){
22 | args = new String[] {"someone@example.com","myself@example.com","Hello !"};
23 | }
24 | NettyTransceiver client = new NettyTransceiver(new InetSocketAddress(10000));
25 | Mail proxy = (Mail) SpecificRequestor.getClient(Mail.class, client);
26 | LogUtil.println("ClientAvroRPC built OK, got proxy, ready to send data ...");
27 | Message message = new Message();
28 | message.setTo(new Utf8(args[0]));
29 | message.setFrom(new Utf8(args[1]));
30 | message.setBody(new Utf8(args[2]));
31 | LogUtil.println("Calling proxy.send with message: " + message.toString());
32 | LogUtil.println("Result from server: " + proxy.send(message));
33 | client.close();
34 | }
35 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe10/ProxyServerAvroRPC.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe10;
2 |
3 | import java.io.IOException;
4 | import java.net.InetSocketAddress;
5 |
6 | import netty.cookbook.common.LogUtil;
7 |
8 | import org.apache.avro.ipc.NettyServer;
9 | import org.apache.avro.ipc.Server;
10 | import org.apache.avro.ipc.specific.SpecificResponder;
11 | import org.apache.avro.util.Utf8;
12 |
13 | import avro.Mail;
14 | import avro.Message;
15 |
16 | /**
17 | * @author trieu
18 | *
19 | */
20 | public class ProxyServerAvroRPC {
21 | public static class MailImpl implements Mail {
22 | public Utf8 send(Message message) {
23 | String s = String.format("message details, to:%s from:%s body:%s", message.getTo(), message.getFrom(), message.getBody());
24 | LogUtil.println(s);
25 | return new Utf8("Sent OK to "+ message.getTo());
26 | }
27 | }
28 | private static Server server;
29 | static void startServer() throws IOException {
30 | server = new NettyServer(new SpecificResponder(Mail.class,new MailImpl()), new InetSocketAddress(10000));
31 | }
32 | public static void main(String[] args) throws Exception {
33 | LogUtil.println("Starting ServerAvroRPC");
34 | startServer();
35 | LogUtil.println("ServerAvroRPC started and wait for 15s");
36 | Thread.sleep(15000);
37 | server.close();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe2/Receiver.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe2;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.socket.SocketChannel;
8 | import io.netty.handler.codec.string.StringDecoder;
9 | import io.netty.handler.codec.string.StringEncoder;
10 | import netty.cookbook.common.BootstrapTemplate;
11 |
12 | public class Receiver {
13 | static final int PORT = 8007;
14 | static final String HOST = "127.0.0.1";
15 | public static void main(String[] args) throws Exception {
16 | ChannelInitializer initializer = new ChannelInitializer() {
17 | @Override
18 | public void initChannel(SocketChannel ch) throws Exception {
19 | ChannelPipeline p = ch.pipeline();
20 | p.addLast(new StringEncoder());
21 | p.addLast(new StringDecoder());
22 | p.addLast(new ChannelInboundHandlerAdapter() {
23 | @Override
24 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
25 | System.out.println(msg);
26 | ctx.close();
27 | }
28 | });
29 | }
30 | };
31 | BootstrapTemplate.newServerBootstrap(HOST, PORT, initializer);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe2/Sender.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe2;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.socket.SocketChannel;
8 | import io.netty.handler.codec.string.StringDecoder;
9 | import io.netty.handler.codec.string.StringEncoder;
10 | import netty.cookbook.common.BootstrapTemplate;
11 |
12 | public class Sender {
13 | static final int PORT = 8007;
14 | static final String HOST = "127.0.0.1";
15 |
16 | public static void main(String[] args) throws InterruptedException {
17 | final String msg = "This is a long message";
18 | ChannelInitializer initializer = new ChannelInitializer() {
19 | @Override
20 | public void initChannel(SocketChannel ch) throws Exception {
21 | ChannelPipeline p = ch.pipeline();
22 | p.addLast(new StringEncoder());
23 | p.addLast(new StringDecoder());
24 | p.addLast(new ChannelInboundHandlerAdapter() {
25 | @Override
26 | public void channelActive(ChannelHandlerContext ctx)
27 | throws Exception {
28 | //on ready to send
29 | ctx.writeAndFlush(msg);
30 | }
31 | @Override
32 | public void channelRead(ChannelHandlerContext ctx,
33 | Object data) throws Exception {
34 | //on receive
35 | System.out.println("got " + data);
36 | }
37 | });
38 | }
39 | };
40 | BootstrapTemplate.newClientBootstrap(HOST, PORT, initializer );
41 | Thread.sleep(5000);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe3/PurchaseClient.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe3;
2 |
3 | import io.netty.channel.ChannelHandler;
4 | import io.netty.channel.ChannelInitializer;
5 | import io.netty.channel.ChannelPipeline;
6 | import io.netty.channel.socket.SocketChannel;
7 | import netty.cookbook.common.BootstrapTemplate;
8 | import netty.cookbook.common.CallbackProcessor;
9 | import netty.cookbook.common.model.PurchaseData;
10 |
11 | public class PurchaseClient {
12 | String host; int port;
13 | public PurchaseClient(String host, int port) {
14 | super();
15 | this.host = host;
16 | this.port = port;
17 | }
18 | public PurchaseClient send(PurchaseData message, CallbackProcessor asynchCall) throws Exception{
19 | ChannelHandler clientHandler = new PurchaseClientHandler(message, asynchCall);
20 | ChannelInitializer initializer = new ChannelInitializer() {
21 | @Override
22 | public void initChannel(SocketChannel ch) throws Exception {
23 | ChannelPipeline p = ch.pipeline();
24 | p.addLast(new PurchaseDataDecoder());
25 | p.addLast(new PurchaseDataEncoder());
26 | p.addLast(clientHandler);
27 | }
28 | };
29 | BootstrapTemplate.newClientBootstrap(host, port, initializer );
30 | return this;
31 | }
32 | public static void main(String[] args) throws Exception {
33 | int unixTime = (int) (System.currentTimeMillis() / 1000L);
34 | PurchaseData data = new PurchaseData(1001, 499.99f, "Trieu", "Amazon", unixTime, false );
35 | new PurchaseClient("127.0.0.1",8007).send(data, rs -> {
36 | System.out.println(rs);
37 | });
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe3/PurchaseDataDecoder.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe3;
2 |
3 | import netty.cookbook.chapter2.recipe6.NettyMonitorIO;
4 | import io.netty.buffer.ByteBuf;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.handler.codec.serialization.ClassResolvers;
7 | import io.netty.handler.codec.serialization.ObjectDecoder;
8 |
9 | public class PurchaseDataDecoder extends ObjectDecoder {
10 | public PurchaseDataDecoder() {
11 | super(ClassResolvers.weakCachingConcurrentResolver(null));
12 | }
13 | @Override
14 | protected Object decode(ChannelHandlerContext ctx, ByteBuf buf)
15 | throws Exception {
16 | Object object = super.decode(ctx, buf);
17 | NettyMonitorIO.updateDataIn(buf);
18 | return object;
19 | }
20 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe3/PurchaseDataEncoder.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe3;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.handler.codec.serialization.ObjectEncoder;
6 |
7 | import java.io.Serializable;
8 |
9 | import netty.cookbook.chapter2.recipe6.NettyMonitorIO;
10 |
11 | public class PurchaseDataEncoder extends ObjectEncoder {
12 | @Override
13 | protected void encode(ChannelHandlerContext ctx, Serializable msg, ByteBuf buf) throws Exception {
14 | super.encode(ctx, msg, buf);
15 | NettyMonitorIO.updateDataOut(buf);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe3/PurchaseServer.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe3;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.ChannelInboundHandlerAdapter;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.socket.SocketChannel;
8 | import netty.cookbook.common.BootstrapTemplate;
9 | import netty.cookbook.common.model.PurchaseData;
10 |
11 | import org.apache.log4j.Logger;
12 |
13 | public class PurchaseServer {
14 | final static Logger logger = Logger.getLogger(PurchaseServer.class);
15 |
16 | static final int PORT = 8007;
17 | static final String HOST = "127.0.0.1";
18 |
19 | public static void main(String[] args) throws Exception {
20 | ChannelInitializer initializer = new ChannelInitializer() {
21 | @Override
22 | public void initChannel(SocketChannel ch) throws Exception {
23 | ChannelPipeline p = ch.pipeline();
24 | p.addLast(new PurchaseDataDecoder());
25 | p.addLast(new PurchaseDataEncoder());
26 | p.addLast(new ChannelInboundHandlerAdapter() {
27 | @Override
28 | public void channelRead(ChannelHandlerContext ctx,
29 | Object data) throws Exception {
30 | System.out.println("processed Purchase " + data);
31 | PurchaseData processed = new PurchaseData(data, true);
32 | ctx.writeAndFlush(processed);
33 | }
34 | });
35 | }
36 | };
37 | BootstrapTemplate.newServerBootstrap(HOST, PORT, initializer);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe6/NettyMonitorIO.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe6;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | import java.text.DateFormat;
6 | import java.text.SimpleDateFormat;
7 | import java.util.Date;
8 | import java.util.Timer;
9 | import java.util.TimerTask;
10 | import java.util.concurrent.ConcurrentHashMap;
11 | import java.util.concurrent.ConcurrentMap;
12 |
13 | /**
14 | * @author trieunt
15 | *
16 | */
17 | public class NettyMonitorIO {
18 | static final DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
19 | static ConcurrentMap dataOutStats = new ConcurrentHashMap();
20 | static ConcurrentMap dataInStats = new ConcurrentHashMap();
21 | public static long updateDataOut(ByteBuf buf) {
22 | String time = DATE_TIME_FORMAT.format(new Date());
23 | long c = dataOutStats.getOrDefault(time, 0L) + buf.readableBytes();
24 | dataOutStats.put(time, c);
25 | return c;
26 | }
27 | public static long updateDataIn(ByteBuf buf) {
28 | String time = DATE_TIME_FORMAT.format(new Date());
29 | long c = dataInStats.getOrDefault(time, 0L) + buf.writableBytes();
30 | dataInStats.put(time, c);
31 | return c;
32 | }
33 | static {
34 | new Timer(true).schedule(new TimerTask() {
35 | @Override
36 | public void run() {
37 | System.out.println("--------------------------------");
38 | System.out.println("Data In Stats:");
39 | dataInStats.forEach((String key, Long val)->{
40 | System.out.println(key + " : "+val);
41 | });
42 | System.out.println("Data Out Stats:");
43 | dataOutStats.forEach((String key, Long val)->{
44 | System.out.println(key + " : "+val);
45 | });
46 | }
47 | }, 2000, 2000);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe7/HeartBeatHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe7;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.buffer.Unpooled;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.channel.SimpleChannelInboundHandler;
7 | import io.netty.channel.socket.DatagramPacket;
8 | import io.netty.util.CharsetUtil;
9 |
10 | import java.util.Date;
11 | import java.util.LinkedList;
12 | import java.util.Queue;
13 | import java.util.Timer;
14 | import java.util.TimerTask;
15 |
16 | public class HeartBeatHandler extends
17 | SimpleChannelInboundHandler {
18 | private static final Queue logQueue = new LinkedList();
19 | static String log(String log) {
20 | return String.valueOf(logQueue.add(log));
21 | }
22 | static {
23 | new Timer(true).schedule(new TimerTask() {
24 | @Override
25 | public void run() {
26 | while ( ! logQueue.isEmpty() ) {
27 | // log to Kafka or somewhere
28 | String s = logQueue.poll();
29 | if(s != null){
30 | System.out.println(s);
31 | }
32 | }
33 | }
34 | }, 1000, 2000);
35 | }
36 |
37 | @Override
38 | public void channelReadComplete(ChannelHandlerContext ctx) {
39 | ctx.flush();
40 | }
41 |
42 | @Override
43 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
44 | cause.printStackTrace();
45 | // We don't close the channel because we can keep serving requests.
46 | }
47 |
48 | @Override
49 | protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
50 | System.err.println(packet);
51 | String s = packet.content().toString(CharsetUtil.UTF_8);
52 | System.out.println(s);
53 | ByteBuf buf = Unpooled.copiedBuffer("I'm alive at "+new Date(), CharsetUtil.UTF_8);
54 | ctx.write(new DatagramPacket(buf, packet.sender()));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe7/ImportantServer.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe7;
2 |
3 | import io.netty.channel.EventLoopGroup;
4 | import io.netty.channel.nio.NioEventLoopGroup;
5 | import netty.cookbook.common.BootstrapTemplate;
6 |
7 | /**
8 | * @author trieu
9 | *
10 | * demo for HeartBeat monitor
11 | *
12 | */
13 | public class ImportantServer {
14 | private static final int PORT = 8080;
15 | public static void main(String[] args) throws Exception {
16 | EventLoopGroup loopGroup = new NioEventLoopGroup();
17 | try {
18 | BootstrapTemplate.newBootstrapUDP(loopGroup, new HeartBeatHandler(), PORT)
19 | .sync().channel().closeFuture().await();
20 | } finally {
21 | loopGroup.shutdownGracefully();
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe8/SimpleSctpClient.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe8;
2 |
3 | import io.netty.bootstrap.Bootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.EventLoopGroup;
8 | import io.netty.channel.nio.NioEventLoopGroup;
9 | import io.netty.channel.sctp.SctpChannel;
10 | import io.netty.channel.sctp.SctpChannelOption;
11 | import io.netty.channel.sctp.nio.NioSctpChannel;
12 |
13 |
14 | public final class SimpleSctpClient {
15 |
16 | static final String HOST = System.getProperty("host", "127.0.0.1");
17 | static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
18 |
19 | public static void main(String[] args) throws Exception {
20 | EventLoopGroup loopGroup = new NioEventLoopGroup();
21 | try {
22 | ChannelFuture f = new Bootstrap().group(loopGroup)
23 | .channel(NioSctpChannel.class)
24 | // set SCTP option
25 | .option(SctpChannelOption.SCTP_NODELAY, true)
26 | .handler(new ChannelInitializer() {
27 | @Override
28 | public void initChannel(SctpChannel ch) throws Exception {
29 | ChannelPipeline p = ch.pipeline();
30 | p.addLast(new SimpleSctpClientHandler());
31 | }
32 | }).connect(HOST, PORT).sync();
33 | f.channel().closeFuture().sync();
34 | } finally {
35 | loopGroup.shutdownGracefully();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe8/SimpleSctpClientHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe8;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.buffer.Unpooled;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.channel.ChannelInboundHandlerAdapter;
7 | import io.netty.channel.sctp.SctpMessage;
8 | import io.netty.util.CharsetUtil;
9 |
10 |
11 | public class SimpleSctpClientHandler extends ChannelInboundHandlerAdapter {
12 | private final ByteBuf firstMessage, secondMessage;
13 | public SimpleSctpClientHandler() {
14 | firstMessage = Unpooled.copiedBuffer("first message",CharsetUtil.UTF_8);
15 | secondMessage = Unpooled.copiedBuffer("second message",CharsetUtil.UTF_8);
16 | }
17 | @Override
18 | public void channelActive(ChannelHandlerContext ctx) {
19 | ctx.write(new SctpMessage(0, 0, firstMessage));
20 | ctx.write(new SctpMessage(0, 0, secondMessage));
21 | ctx.flush();
22 | }
23 |
24 | @Override
25 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
26 | System.out.println(msg);
27 | }
28 |
29 | @Override
30 | public void channelReadComplete(ChannelHandlerContext ctx) {
31 | ctx.flush();
32 | }
33 |
34 | @Override
35 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
36 | // Close the connection when an exception is raised.
37 | cause.printStackTrace();
38 | ctx.close();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe8/SimpleSctpServer.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe8;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelOption;
7 | import io.netty.channel.ChannelPipeline;
8 | import io.netty.channel.EventLoopGroup;
9 | import io.netty.channel.nio.NioEventLoopGroup;
10 | import io.netty.channel.sctp.SctpChannel;
11 | import io.netty.channel.sctp.nio.NioSctpServerChannel;
12 | import io.netty.handler.logging.LogLevel;
13 | import io.netty.handler.logging.LoggingHandler;
14 |
15 |
16 | public final class SimpleSctpServer {
17 |
18 | static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
19 |
20 | public static void main(String[] args) throws Exception {
21 | EventLoopGroup mainLoop = new NioEventLoopGroup(1);
22 | EventLoopGroup workerLoop = new NioEventLoopGroup();
23 | try {
24 | ChannelFuture f = new ServerBootstrap().group(mainLoop, workerLoop)
25 | .channel(NioSctpServerChannel.class)
26 | .option(ChannelOption.SO_BACKLOG, 100)
27 | .handler(new LoggingHandler(LogLevel.INFO))
28 | .childHandler(new ChannelInitializer() {
29 | @Override
30 | public void initChannel(SctpChannel ch) throws Exception {
31 | ChannelPipeline p = ch.pipeline();
32 | p.addLast(new SimpleSctpServerHandler());
33 | }
34 | }).bind(PORT).sync();
35 | f.channel().closeFuture().sync();
36 | } finally {
37 | mainLoop.shutdownGracefully();
38 | workerLoop.shutdownGracefully();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe8/SimpleSctpServerHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe8;
2 |
3 | import io.netty.channel.ChannelHandler.Sharable;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 | import io.netty.channel.sctp.SctpMessage;
7 | import io.netty.util.CharsetUtil;
8 |
9 | /**
10 | * Handler implementation for the SCTP echo server.
11 | */
12 | @Sharable
13 | public class SimpleSctpServerHandler extends ChannelInboundHandlerAdapter {
14 | @Override
15 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
16 | System.out.println(msg);
17 | if(msg instanceof SctpMessage){
18 | SctpMessage sctpMsg = (SctpMessage) msg;
19 | System.out.println(sctpMsg.content().toString(CharsetUtil.UTF_8));
20 | ctx.write(sctpMsg);
21 | }
22 | }
23 |
24 | @Override
25 | public void channelReadComplete(ChannelHandlerContext ctx) {
26 | ctx.flush();
27 | }
28 |
29 | @Override
30 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
31 | // Close the connection when an exception is raised.
32 | cause.printStackTrace();
33 | ctx.close();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe9/FileReceiver.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe9;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.nio.file.Files;
7 |
8 | import com.butor.netty.handler.codec.ftp.DataReceiver;
9 |
10 | class FileReceiver implements DataReceiver {
11 | @Override
12 | public void receive(String name, InputStream data) throws IOException {
13 | System.out.println("got file: [" + name + "]");
14 | //copy to local folder
15 | Files.copy(data, new File("./data/"+name).toPath());
16 | }
17 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter2/recipe9/SimpleServerFTP.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter2.recipe9;
2 |
3 | import io.netty.channel.ChannelInitializer;
4 | import io.netty.channel.ChannelPipeline;
5 | import io.netty.channel.socket.SocketChannel;
6 | import netty.cookbook.common.BootstrapTemplate;
7 |
8 | import com.butor.netty.handler.codec.ftp.CrlfStringDecoder;
9 | import com.butor.netty.handler.codec.ftp.DataReceiver;
10 | import com.butor.netty.handler.codec.ftp.FtpServerHandler;
11 | import com.butor.netty.handler.codec.ftp.cmd.DefaultCommandExecutionTemplate;
12 |
13 | public class SimpleServerFTP {
14 | public static void main(String... args) throws Exception {
15 | DataReceiver dataReceiver = new FileReceiver();
16 | final DefaultCommandExecutionTemplate tpl = new DefaultCommandExecutionTemplate(dataReceiver);
17 | ChannelInitializer initializer = new ChannelInitializer() {
18 | @Override
19 | protected void initChannel(SocketChannel ch) throws Exception {
20 | ChannelPipeline p = ch.pipeline();
21 | p.addLast(new CrlfStringDecoder());
22 | p.addLast(new FtpServerHandler(tpl));
23 | }
24 | };
25 | BootstrapTemplate.newServerBootstrap("127.0.0.1", 2121, initializer);
26 | }
27 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter3/recipe1/Echo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter3.recipe1;
2 |
3 | import org.jboss.netty.handler.codec.http.HttpMethod;
4 | import org.restexpress.Request;
5 | import org.restexpress.Response;
6 | import org.restexpress.RestExpress;
7 |
8 | /**
9 | * @author toddf
10 | * @since June 29, 2012
11 | */
12 | public class Echo {
13 | static class RestfulHandler {
14 | public String read(Request req, Response res) {
15 | String value = req.getHeader("echo");
16 | res.setContentType("text/xml");
17 |
18 | if (value == null) {
19 | return "no value specified";
20 | } else {
21 | return String.format(
22 | "%s", value);
23 | }
24 | }
25 | }
26 |
27 | public static void main(String[] args) {
28 | RestExpress server = new RestExpress().setName("Echo");
29 |
30 | server.uri("/echo", new RestfulHandler()).method(HttpMethod.GET)
31 | .noSerialization();
32 |
33 | server.bind(8000);
34 | server.awaitShutdown();
35 | }
36 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter4/recipe5/PubSubDemo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter4.recipe5;
2 |
3 | import netty.cookbook.chapter4.recipe5.WebUrl.FacebookStats;
4 |
5 | public class PubSubDemo {
6 |
7 | public static void main(String[] args) {
8 | WebUrl model = new WebUrl("http://vnexpress.net");
9 | SocialAnalyticUpdater observer = new SocialAnalyticUpdater(model);
10 |
11 | for (FacebookStats stats : model.getFacebookStats()) {
12 | stats.setLikeCount(stats.getLikeCount() + 1);
13 | }
14 |
15 | for (FacebookStats stats : model.getFacebookStats()) {
16 | stats.setShareCount(stats.getShareCount() + 1);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter4/recipe5/SocialAnalyticUpdater.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter4.recipe5;
2 |
3 | import java.beans.PropertyChangeEvent;
4 | import java.beans.PropertyChangeListener;
5 |
6 | public class SocialAnalyticUpdater implements PropertyChangeListener {
7 | public SocialAnalyticUpdater(WebUrl model) {
8 | model.addChangeListener(this);
9 | }
10 |
11 | @Override
12 | public void propertyChange(PropertyChangeEvent event) {
13 | System.out.println("Changed property: " + event.getPropertyName() + " [old -> "
14 | + event.getOldValue() + "] | [new -> " + event.getNewValue() +"]");
15 | }
16 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter4/recipe5/WebUrl.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter4.recipe5;
2 |
3 | import java.beans.PropertyChangeEvent;
4 | import java.beans.PropertyChangeListener;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class WebUrl {
9 | public static final String LIKE_COUNT = "likeCount";
10 | public static final String SHARE_COUNT = "shareCount";
11 |
12 | private List stats = new ArrayList();
13 | private List listener = new ArrayList();
14 | private String url;
15 |
16 | public class FacebookStats {
17 | private long likeCount;
18 | private long shareCount;
19 |
20 | public FacebookStats(long like, long share) {
21 | this.likeCount = like;
22 | this.shareCount = share;
23 | }
24 |
25 | public long getLikeCount() {
26 | return likeCount;
27 | }
28 |
29 | public void setLikeCount(long like) {
30 | notifyListeners(this, LIKE_COUNT, this.likeCount, this.likeCount = like);
31 |
32 | }
33 |
34 | public long getShareCount() {
35 | return shareCount;
36 | }
37 |
38 | public void setShareCount(long shareCount) {
39 | notifyListeners(this, SHARE_COUNT, this.shareCount, this.shareCount = shareCount);
40 | }
41 | }
42 |
43 | public List getFacebookStats() {
44 | return stats;
45 | }
46 |
47 | public String getUrl() {
48 | return url;
49 | }
50 |
51 | public WebUrl(String url) {
52 | this.url = url;
53 | stats.add(new FacebookStats(0, 0));
54 | }
55 |
56 | private void notifyListeners(Object object, String property,
57 | long oldValue, long newValue) {
58 | for (PropertyChangeListener name : listener) {
59 | name.propertyChange(new PropertyChangeEvent(this, property, oldValue, newValue));
60 | }
61 | }
62 |
63 | public void addChangeListener(PropertyChangeListener newListener) {
64 | listener.add(newListener);
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter8/recipe3/HttpServer.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter8.recipe3;
2 |
3 |
4 | import netty.cookbook.common.BootstrapTemplate;
5 |
6 |
7 | public class HttpServer {
8 | static String host = "localhost:8080";
9 |
10 | public final static String DEFAULT_CLASSPATH = "rfx";
11 | public final static String SERVER_INFO_VERSION = "RfxS2Http/0.1";
12 |
13 | int port;
14 | String ip;
15 |
16 | static boolean debug = false;
17 |
18 | public final static void setDebug(boolean debug) {
19 | HttpServer.debug = debug;
20 | }
21 |
22 | public final static boolean isDebug() {
23 | return debug;
24 | }
25 |
26 | void setHost(String ip, int port) {
27 | this.port = port;
28 | this.ip = ip;
29 | host = this.ip+":"+port;
30 | }
31 |
32 | public HttpServer(String ip, int port) {
33 | setHost(ip, port);
34 | }
35 |
36 | public static String getHost() {
37 | return host;
38 | }
39 |
40 | public void run() throws Exception {
41 | BootstrapTemplate.newHttpServerBootstrap(ip, port, new PublicHttpServerInitializer());
42 | }
43 |
44 | public static void main(String[] args) throws Exception {
45 | HttpServer httpServer = new HttpServer("*", 3001);
46 | httpServer.run();
47 | }
48 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/chapter8/recipe3/PublicHttpServerInitializer.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.chapter8.recipe3;
2 |
3 |
4 | import io.netty.channel.ChannelInitializer;
5 | import io.netty.channel.ChannelPipeline;
6 | import io.netty.channel.socket.SocketChannel;
7 | import io.netty.handler.codec.http.HttpRequestDecoder;
8 | import io.netty.handler.codec.http.HttpResponseEncoder;
9 |
10 | public class PublicHttpServerInitializer extends ChannelInitializer {
11 |
12 | @Override
13 | public void initChannel(SocketChannel ch) throws Exception {
14 | // Create a default pipeline implementation.
15 | ChannelPipeline p = ch.pipeline();
16 |
17 | // Uncomment the following line if you want HTTPS
18 | //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
19 | //engine.setUseClientMode(false);
20 | //p.addLast("ssl", new SslHandler(engine));
21 | //TODO support SSL HTTP
22 |
23 | p.addLast("decoder", new HttpRequestDecoder());
24 | // Uncomment the following line if you don't want to handle HttpChunks.
25 | //p.addLast("aggregator", new HttpObjectAggregator(1048576));
26 | p.addLast("encoder", new HttpResponseEncoder());
27 | // Remove the following line if you don't want automatic content compression.
28 | //p.addLast("deflater", new HttpContentCompressor());
29 | p.addLast("handler", new HttpEventProcessingHandler());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/CallbackActor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import akka.actor.UntypedActor;
4 |
5 | public class CallbackActor extends UntypedActor {
6 |
7 | @Override
8 | public void onReceive(Object arg0) throws Exception {
9 | // TODO Auto-generated method stub
10 |
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/CallbackProcessor.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | @FunctionalInterface
4 | public interface CallbackProcessor {
5 | public void process(Object obj);
6 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/LogUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | public class LogUtil {
4 |
5 | public static void println(Object obj){
6 | System.out.println(obj);
7 | }
8 |
9 | public static void println(String obj){
10 | System.out.println(obj);
11 | }
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/TcpChannelHandler.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 |
5 | @FunctionalInterface
6 | public interface TcpChannelHandler {
7 | public void process(ChannelHandlerContext ctx, Object msg);
8 | }
9 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/UrlUtil.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | public class UrlUtil {
7 | public final static String REGEX_FOR_ROOT_DOMAIN = ".*\\.(?=.*\\.)";
8 |
9 | public static String getRootDomain(String fullUrl) throws MalformedURLException{
10 | return new URL(fullUrl).getHost().replaceAll(REGEX_FOR_ROOT_DOMAIN, "");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/http/ContentTypePool.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | public class ContentTypePool {
4 | public static final String GIF = "image/gif";
5 | public static final String TRACKING_GIF = GIF;
6 | public static final String JPEG = "image/jpeg";
7 |
8 | public static final String JAVA_SCRIPT = "application/javascript; charset=utf-8";
9 | public static final String XML = "application/xml; charset=utf-8";
10 | public static final String JSON = "application/json; charset=utf-8";
11 |
12 | public static final String TEXT_UTF8 = "text/plain; charset=UTF-8";
13 | public static final String HTML_UTF8 = "text/html; charset=UTF-8";
14 | }
15 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/http/HttpOutputResource.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.http;
2 |
3 | import io.netty.buffer.ByteBuf;
4 |
5 | public class HttpOutputResource {
6 | ByteBuf byteBuf;
7 | long length;
8 | long lastModified;
9 |
10 |
11 | public HttpOutputResource(ByteBuf byteBuf, long lastModified) {
12 | super();
13 | this.byteBuf = byteBuf;
14 | this.length = byteBuf.readableBytes();
15 | this.lastModified = lastModified;
16 | }
17 |
18 | public ByteBuf getByteBuf() {
19 | return byteBuf;
20 | }
21 |
22 | public void setByteBuf(ByteBuf byteBuf) {
23 | this.byteBuf = byteBuf;
24 | }
25 |
26 | public long getLength() {
27 | return length;
28 | }
29 |
30 | public void setLength(long length) {
31 | this.length = length;
32 | }
33 |
34 | public long getLastModified() {
35 | return lastModified;
36 | }
37 |
38 | public void setLastModified(long lastModified) {
39 | this.lastModified = lastModified;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/model/PurchaseData.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.model;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.gson.Gson;
6 |
7 | public class PurchaseData implements Serializable{
8 | private static final long serialVersionUID = -5467453661148034694L;
9 | private final int itemId;
10 | private final float price;
11 | private final String buyer;
12 | private final String seller;
13 | private final int unixTime;
14 | private final boolean processed;
15 | public PurchaseData(int itemId, float price, String buyer, String seller,
16 | int unixTime, boolean processed) {
17 | super();
18 | this.itemId = itemId;
19 | this.price = price;
20 | this.buyer = buyer;
21 | this.seller = seller;
22 | this.unixTime = unixTime;
23 | this.processed = processed;
24 | }
25 | public PurchaseData(Object obj, boolean processed) {
26 | super();
27 | PurchaseData data = (PurchaseData)obj;
28 | this.itemId = data.itemId;
29 | this.price = data.price;
30 | this.buyer = data.buyer;
31 | this.seller = data.seller;
32 | this.unixTime = data.unixTime;
33 | this.processed = processed;
34 | }
35 | public float getPrice() {
36 | return price;
37 | }
38 | public String getBuyer() {
39 | return buyer;
40 | }
41 | public String getSeller() {
42 | return seller;
43 | }
44 | public int getUnixTime() {
45 | return unixTime;
46 | }
47 | public int getItemId() {
48 | return itemId;
49 | }
50 | public boolean isProcessed() {
51 | return processed;
52 | }
53 | @Override
54 | public String toString() {
55 | return new Gson().toJson(this);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/redis/RedisCommand.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import netty.cookbook.common.StringPool;
4 | import redis.clients.jedis.Jedis;
5 | import redis.clients.jedis.ShardedJedis;
6 | import redis.clients.jedis.ShardedJedisPool;
7 | import redis.clients.jedis.exceptions.JedisException;
8 |
9 | public abstract class RedisCommand {
10 | protected ShardedJedisPool jedisPool;
11 | protected ShardedJedis shardedJedis = null;
12 | protected Jedis jedis = null;
13 |
14 | public RedisCommand(ShardedJedisPool jedisPool) {
15 | super();
16 | if (jedisPool == null) {
17 | throw new IllegalArgumentException("jedisPool is NULL!");
18 | }
19 | this.jedisPool = jedisPool;
20 | }
21 |
22 | public T execute() {
23 | boolean commited = false;
24 | T rs = null;
25 | try {
26 | shardedJedis = jedisPool.getResource();
27 | if (shardedJedis != null) {
28 | jedis = shardedJedis.getShard(StringPool.BLANK);
29 | rs = build();
30 | commited = true;
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | } finally {
35 | freeRedisResource(jedisPool, shardedJedis, commited);
36 | }
37 | return rs;
38 | }
39 |
40 | public static void freeRedisResource(ShardedJedisPool jedisPool, ShardedJedis shardedJedis, boolean isCommited){
41 | if (shardedJedis != null && jedisPool != null) {
42 | if (isCommited) {
43 | jedisPool.returnResource(shardedJedis);
44 | } else {
45 | jedisPool.returnBrokenResource(shardedJedis);
46 | }
47 | }
48 | }
49 |
50 | //define the logic at implementer
51 | protected abstract T build() throws JedisException;
52 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/main/java/netty/cookbook/common/redis/RedisInfo.java:
--------------------------------------------------------------------------------
1 | package netty.cookbook.common.redis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import redis.clients.jedis.JedisShardInfo;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | public class RedisInfo {
10 | public static final String LOCALHOST_STR = "localhost";
11 |
12 | private String host;
13 | private int port;
14 | private String auth;
15 | private ShardedJedisPool shardedJedisPool;
16 |
17 | protected void initThePool(){
18 | List shardInfos = new ArrayList(1);
19 | shardInfos.add(new JedisShardInfo(getHost(), getPort(), 0));
20 | shardedJedisPool = new ShardedJedisPool(RedisConnectionPoolConfig.getJedisPoolConfigInstance(), shardInfos);
21 | }
22 |
23 | public RedisInfo(String host, int port) {
24 | this.host = host;
25 | this.port = port;
26 | initThePool();
27 | }
28 |
29 | public RedisInfo(String host, int port,String auth) {
30 | this.host = host;
31 | this.port = port;
32 | this.auth = auth;
33 | initThePool();
34 | }
35 |
36 | public String getHost() {
37 | return host;
38 | }
39 |
40 | public int getPort() {
41 | return port;
42 | }
43 |
44 | public String getAuth() {
45 | return auth;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object obj) {
50 | if (obj instanceof RedisInfo) {
51 | RedisInfo hp = (RedisInfo) obj;
52 |
53 | String thisHost = convertHost(host);
54 | String hpHost = convertHost(hp.host);
55 | return port == hp.port && thisHost.equals(hpHost);
56 |
57 | }
58 |
59 | return false;
60 | }
61 |
62 | public ShardedJedisPool getShardedJedisPool() {
63 | return shardedJedisPool;
64 | }
65 |
66 | @Override
67 | public String toString() {
68 | return host + ":" + port;
69 | }
70 |
71 | private String convertHost(String host) {
72 | if (host.equals("127.0.0.1"))
73 | return LOCALHOST_STR;
74 | else if (host.equals("::1"))
75 | return LOCALHOST_STR;
76 |
77 | return host;
78 | }
79 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/test/java/classic/tcp/TCPClient.java:
--------------------------------------------------------------------------------
1 | package classic.tcp;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.DataOutputStream;
5 | import java.io.InputStreamReader;
6 | import java.net.Socket;
7 |
8 | class TCPClient {
9 | public static void main(String argv[]) throws Exception {
10 | String sentence = "hello";
11 | String modifiedSentence;
12 | //BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
13 | Socket clientSocket = new Socket("localhost", 6789);
14 | DataOutputStream outToServer = new DataOutputStream(
15 | clientSocket.getOutputStream());
16 | BufferedReader inFromServer = new BufferedReader(new InputStreamReader(
17 | clientSocket.getInputStream()));
18 | //sentence = inFromUser.readLine();
19 | outToServer.writeBytes(sentence + '\n');
20 | modifiedSentence = inFromServer.readLine();
21 | System.out.println("FROM SERVER: " + modifiedSentence);
22 | clientSocket.close();
23 | }
24 | }
--------------------------------------------------------------------------------
/netty-cookbook-java-src/src/test/java/classic/tcp/TCPServer.java:
--------------------------------------------------------------------------------
1 | package classic.tcp;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.DataOutputStream;
5 | import java.io.InputStreamReader;
6 | import java.net.ServerSocket;
7 | import java.net.Socket;
8 |
9 | public class TCPServer {
10 | public static void main(String argv[]) throws Exception {
11 | String clientSentence;
12 | String capitalizedSentence;
13 | ServerSocket welcomeSocket = new ServerSocket(6789);
14 | while (true) {
15 | Socket connectionSocket = welcomeSocket.accept();
16 | BufferedReader inFromClient = new BufferedReader(
17 | new InputStreamReader(connectionSocket.getInputStream()));
18 | DataOutputStream outToClient = new DataOutputStream(
19 | connectionSocket.getOutputStream());
20 | clientSentence = inFromClient.readLine();
21 | System.out.println("Received: " + clientSentence);
22 | capitalizedSentence = clientSentence.toUpperCase() + '\n';
23 | outToClient.writeBytes(capitalizedSentence);
24 | }
25 | //welcomeSocket.close();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/netty-cookbook-java-src/tools/avro-tools-1.7.7.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trieu/netty-cookbook/6b72058b2dd085a52c7586ced4899490e8ae52df/netty-cookbook-java-src/tools/avro-tools-1.7.7.jar
--------------------------------------------------------------------------------