Last active
October 2, 2016 19:04
-
-
Save john77eipe/13ceb188107f239c230e7c9ebff4f7d6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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