Skip to content

Instantly share code, notes, and snippets.

@john77eipe
Last active October 2, 2016 19:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save john77eipe/13ceb188107f239c230e7c9ebff4f7d6 to your computer and use it in GitHub Desktop.
Save john77eipe/13ceb188107f239c230e7c9ebff4f7d6 to your computer and use it in GitHub Desktop.
package async;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = "/asyncn", asyncSupported = true)
public class AsyncN extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
println("Before starting job");
// cannot call getWriter here
final AsyncContext actx = request.startAsync();
actx.setTimeout(Long.MAX_VALUE);
// set up async listener for fun
actx.addListener(new AsyncListener() {
@Override
public void onComplete(AsyncEvent event) throws IOException {
println("AsyncServletNIO onComplete() called");
}
@Override
public void onError(AsyncEvent event) {
println("AsyncServletNIO onError() " + event.getThrowable());
}
@Override
public void onStartAsync(AsyncEvent event) {
println("AsyncServletNIO onStartAsync()");
}
@Override
public void onTimeout(AsyncEvent event) {
println("AsyncServletNIO onTimeout()");
}
}, request, response);
final ServletInputStream is = request.getInputStream();
final ServletOutputStream os = response.getOutputStream();
// Start NIO Mode!! Can not use regular servlet input stream read/write after this
// AsyncReadListener for clients that are slow to write data,
// and an AsyncWriteListener for clients that are slow to read data.
is.setReadListener(new AsyncReadListener(actx, is, os));
println("After starting job");
}
public static void println(String output) {
System.out.println("[" + Thread.currentThread().getName() + "]" + output);
}
}
package async;
import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import javax.servlet.AsyncContext;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
public class AsyncReadListener implements ReadListener {
private final AsyncContext ac;
private final ServletInputStream is;
private final ServletOutputStream os;
final Queue<String> queue = new LinkedBlockingQueue<String>();
public AsyncReadListener(AsyncContext ac, ServletInputStream is, ServletOutputStream os) {
this.ac = ac;
this.is = is;
this.os = os;
}
@Override
public void onDataAvailable() throws IOException {
println("AsyncReadListener: data available ");
int len = -1;
byte[] b = new byte[32];
StringBuilder sb = new StringBuilder();
// The ReadListener will be invoked again when
// the input#isReady is changed from false to true
while (is.isReady() && (len = is.read(b)) != -1) {
String data = new String(b, 0, len);
println("Reading data: "+data);
sb.append(data);
}
queue.add(sb.toString());
}
@Override
public void onAllDataRead() throws IOException {
println("AsyncReadListener: All data read.. ");
// now all data are read, set up a WriteListener to write
os.setWriteListener(new AsyncWriteListener(ac, queue, os));
}
@Override
public void onError(Throwable t) {
println("AsyncReadListener onError() " + t);
t.printStackTrace();
ac.complete();
}
public static void println(String output) {
System.out.println("[" + Thread.currentThread().getName() + "]" + output);
}
}
package async;
import java.io.IOException;
import java.util.Queue;
import javax.servlet.AsyncContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
public class AsyncWriteListener implements WriteListener {
private final AsyncContext ac;
private final Queue<String> queue;
private final ServletOutputStream os;
private static final String header = "<html lang=\"en-US\" xmlns=\"http://www.w3.org/1999/xhtml\"><body>Hello";
private static final String footer = "</body></html>";
private boolean writeHeader;
public AsyncWriteListener(AsyncContext ac, Queue<String> queue, ServletOutputStream os) {
this.ac = ac;
this.queue = queue;
this.os = os;
writeHeader = true;
}
@Override
public void onWritePossible() throws IOException {
println("AsyncWriteListener: onWritePossible.. ");
if ( writeHeader ) {
os.println(header);
writeHeader = false;
}
while (queue.peek() != null && os.isReady()) {
String data = queue.poll();
os.print(data);
}
// complete the async process when there is no more data to write
if (queue.peek() == null) {
os.println(footer);
ac.complete();
}
}
@Override
public void onError(Throwable t) {
println("AsyncWriteListener onError() " + t);
t.printStackTrace();
ac.complete();
}
public static void println(String output) {
System.out.println("[" + Thread.currentThread().getName() + "]" + output);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment