Java EE 7 SDK |
This is a simple servlet application that uses the non-blocking I/O API to demonstrate how to write to a response in a non-blocking manner.
This sample application demonstrates how to use the WriteListener
interface in
servlets. The application consists of three elements: the client (ClientTest
),
the server (ServerTest
), and the implementation of the WriteListener
interface (WriteListenerImpl
). The server registers the write listener, and when data
is available to write to the response, it sends chunks of bytes to the client. The chunk size is
pre-configured to simulate blocking (the maximum write buffer size). The client receives the data
from the server and displays it on the page.
Client
In ClientTest.java
, the client initiates an HTTP connection to server and waits
for the response to show it on the page.
@WebServlet(name = "ClientTest", urlPatterns = {"/"}) public class ClientTest extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... String urlPath = "http://" + request.getServerName() + ":" + request.getLocalPort() //8080 + request.getContextPath() + "/ServerTest"; URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); ... conn.connect(); ... BufferedReader input = new BufferedReader(new InputStreamReader(conn.getInputStream())); for (String line; input != null && (line = input.readLine()) != null;) { if (line.length() > 20) { out.println(line.substring(0, 20) + "</br>"); out.flush(); } else if (line.equals("---> Time out")) { out.println(line + "</br>"); out.flush(); } } } ... }
Since the server sends several chunks of bytes, the length of the byte array is larger than the width of most browser windows, so some browsers would not display this correctly. In this sample, the length of the line is truncated to 20 characters.
Server
In ServerTest.java
, after receiving a request the servlet starts the asynchronous request
processing and registers the write listener.
@WebServlet(name="ServerTest", urlPatterns={"/ServerTest"}, asyncSupported = true) public class ServerTest extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... final AsyncContext context = request.startAsync(); final ServletOutputStream output = response.getOutputStream(); output.setWriteListener(new ServerWriteListenerImpl(output, context)); } ... }
WebServlet(..., asyncSupported = true)
is an annotation that specifies the servlet name,
URL, and asynchronous processing support. The method setWriteListener()
registers the write listener for the input stream.
Note: Non-blocking I/O only works with asynchronous request processing in servlets and filters.
Write Listener Implementation
WriteListenerImpl.java
is the implementation of the WriteListener
interface.
public class WriteListenerImpl implements WriteListener { public WriteListenerImpl() { ... } @Override public void onWritePossible() throws IOException { ... while (output.isReady()) { if (System.currentTimeMillis() - startTime > 10000 || count > 10) { output.println("---> Time out"); throw new Exception("Time out"); } System.out.println("Writing data...... "); writeBytes(output, 'a'); count++; } ... }
@Override public void onError(Throwable t) { ... System.out.println("--> onError"); } protected void writeBytes(ServletOutputStream output, char data) throws IOException { byte[] b = new byte[LENGTH]; Arrays.fill(b, 0, LENGTH, (byte) data); output.write(b); ... } }
The method onWritePossible()
is invoked when data is available to write to the response
stream. The container subsequently invokes the writeBytes()
method if and only if
isReady()
returns true. The onError(Throwable t)
method is invoked if
any error or exceptions occur while writing to the response. The isReady()
method returns true
if the underlying data stream is not blocked. At this point, the container invokes the
writeBytes()
method.
You can customize the constructor to handle different parameters. The parameters can be
ServletInputStream
, ServletOutputStream
, or AsyncContext
.
This sample uses ServletOutputStream
and AsyncContext
to implement the
write listener.
This sample application demonstrates the following key features:
WriteListener
interface to avoid waiting for the output stream
to be ready in the application.
Follow these instructions for building, deploying, and running
this sample application:
app_dir
is the sample application base
directory: samples_install_dir/servlet/non-blocking-io-write-war
.
Change directory to app_dir.
mvn
target:Use the command below to run this sample using the Cargo framework:
app_dir>
mvn clean verify cargo:run
You can point Cargo to an already installed and running Glassfish server:
app_dir> mvn clean verify cargo:run -Dglassfish.home=$<glassfish_dir>
(e.g. ../glassfish4)
You can also build, deploy the sample application without Cargo:
app_dir> mvn install
app_dir> asadmin deploy ./target/<app_name>.war
http://<javaee.server.name>:<javaee.server.port>/non-blocking-io-write-war
This is the data from Server. aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa ---> Time out Check server log for more details
app_dir>
asadmin undeploy
<app_name>
clean
to remove the temporary directories
like /target.
app_dir> mvn
clean
Perform the following steps to build, deploy, and run the application using NetBeans IDE:
samples_install_dir/servlet/
directory, select non-blocking-io-write-war
, and click Open Project.non-blocking-io-write-war
and select Run to build, deploy, and run the project.If you have problems when running the application, refer the troubleshooting document.
Copyright © 1997-2013 Oracle and/or its affiliates. All rights reserved.