use of javax.servlet.AsyncListener in project fabric8 by jboss-fuse.
the class MavenDownloadProxyServlet method doGet.
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
String tpath = req.getPathInfo();
if (tpath == null) {
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
if (tpath.startsWith("/")) {
tpath = tpath.substring(1);
}
final String path = tpath;
// state to help synchronize between async timeout handler and ArtifactDownloadFuture ready handler
final AtomicInteger timeoutOrReady = new AtomicInteger(ASYNC_STARTED);
final AsyncContext asyncContext = req.startAsync();
// timeout higher than the one set in:
// org.eclipse.aether.DefaultRepositorySystemSession.setConfigProperty("aether.connector.requestTimeout", N)
asyncContext.setTimeout(this.timeout);
asyncContext.addListener(new AsyncListener() {
@Override
public void onComplete(AsyncEvent event) throws IOException {
}
@Override
public void onTimeout(AsyncEvent event) throws IOException {
if (timeoutOrReady.compareAndSet(ASYNC_STARTED, ASYNC_TIMEOUT)) {
LOGGER.warn("Timeout handling " + ((HttpServletRequest) event.getSuppliedRequest()).getRequestURI());
((HttpServletResponse) event.getAsyncContext().getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Async timeout when downloading Maven artifact");
event.getAsyncContext().complete();
} else {
LOGGER.debug("Timeout handling " + ((HttpServletRequest) event.getSuppliedRequest()).getRequestURI() + ", but download thread completed, continuing process of download.");
}
}
@Override
public void onError(AsyncEvent event) throws IOException {
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
}
});
final AsynchronousFileChannel channel = (AsynchronousFileChannel) req.getAttribute(AsynchronousFileChannel.class.getName());
if (channel != null) /*&& req.getDispatcherType() == DispatcherType.ASYNC*/
{
long size = (Long) req.getAttribute(AsynchronousFileChannel.class.getName() + ".size");
long pos = (Long) req.getAttribute(AsynchronousFileChannel.class.getName() + ".position");
int read = (Integer) req.getAttribute(AsynchronousFileChannel.class.getName() + ".read");
ByteBuffer buffer = (ByteBuffer) req.getAttribute(ByteBuffer.class.getName());
ByteBuffer secondBuffer = (ByteBuffer) req.getAttribute(ByteBuffer.class.getName() + ".second");
if (read > 0) {
pos += read;
if (pos < size) {
req.setAttribute(AsynchronousFileChannel.class.getName() + ".position", pos);
req.setAttribute(ByteBuffer.class.getName(), secondBuffer);
req.setAttribute(ByteBuffer.class.getName() + ".second", buffer);
channel.read(secondBuffer, pos, asyncContext, new CompletionHandler<Integer, AsyncContext>() {
@Override
public void completed(Integer result, AsyncContext attachment) {
req.setAttribute(AsynchronousFileChannel.class.getName() + ".read", result);
// dispatch again, buffers are switched
attachment.dispatch();
}
@Override
public void failed(Throwable exc, AsyncContext attachment) {
Closeables.closeQuietly(channel);
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
attachment.complete();
}
});
}
buffer.flip();
resp.getOutputStream().write(buffer.array(), 0, buffer.remaining());
resp.flushBuffer();
if (pos == size) {
Closeables.closeQuietly(channel);
asyncContext.complete();
}
} else {
Closeables.closeQuietly(channel);
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
asyncContext.complete();
}
return;
}
final ArtifactDownloadFuture future = new ArtifactDownloadFuture(path);
ArtifactDownloadFuture masterFuture = requestMap.putIfAbsent(path, future);
if (masterFuture == null) {
masterFuture = future;
masterFuture.lock();
executorService.execute(new Runnable() {
@Override
public void run() {
try {
File file = download(path);
future.setValue(file);
} catch (Throwable t) {
future.setValue(t);
}
}
});
} else {
masterFuture.lock();
}
masterFuture.addListener(new FutureListener<ArtifactDownloadFuture>() {
@Override
public void operationComplete(ArtifactDownloadFuture future) {
Object value = future.getValue();
if (value instanceof Throwable) {
LOGGER.warn("Error while downloading artifact: {}", ((Throwable) value).getMessage(), value);
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} else if (value instanceof File) {
if (!timeoutOrReady.compareAndSet(ASYNC_STARTED, ASYNC_ARTIFACT_READY)) {
LOGGER.warn("Download thread completed, but asynchronous timeout occurred. Downloading interrupted.");
} else {
File artifactFile = (File) value;
AsynchronousFileChannel channel = null;
try {
channel = AsynchronousFileChannel.open(artifactFile.toPath(), StandardOpenOption.READ);
LOGGER.info("Writing response for file : {}", path);
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("application/octet-stream");
resp.setDateHeader("Date", System.currentTimeMillis());
resp.setHeader("Connection", "close");
resp.setHeader("Server", "MavenProxy Proxy/" + FabricConstants.FABRIC_VERSION);
long size = artifactFile.length();
if (size < Integer.MAX_VALUE) {
resp.setContentLength((int) size);
}
if ("GET".equals(req.getMethod())) {
// Store attributes and start reading
req.setAttribute(AsynchronousFileChannel.class.getName(), channel);
ByteBuffer buffer = ByteBuffer.allocate(1024 * 64);
ByteBuffer secondBuffer = ByteBuffer.allocate(1024 * 64);
req.setAttribute(ByteBuffer.class.getName(), secondBuffer);
req.setAttribute(ByteBuffer.class.getName() + ".second", buffer);
req.setAttribute(AsynchronousFileChannel.class.getName() + ".position", 0l);
req.setAttribute(AsynchronousFileChannel.class.getName() + ".size", size);
channel.read(secondBuffer, 0, asyncContext, new CompletionHandler<Integer, AsyncContext>() {
@Override
public void completed(Integer result, AsyncContext attachment) {
req.setAttribute(AsynchronousFileChannel.class.getName() + ".read", result);
attachment.dispatch();
}
@Override
public void failed(Throwable exc, AsyncContext attachment) {
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
attachment.complete();
}
});
} else if ("HEAD".equals(req.getMethod())) {
asyncContext.complete();
}
future.release();
return;
} catch (Exception e) {
Closeables.closeQuietly(channel);
LOGGER.warn("Error while sending artifact: {}", e.getMessage(), e);
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
} else {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
future.release();
try {
asyncContext.complete();
} catch (IllegalStateException e) {
// Ignore, the response must have already been sent with an error
}
}
});
}
use of javax.servlet.AsyncListener in project presto by prestodb.
the class AsyncPageTransportServlet method processRequest.
protected void processRequest(String requestURI, TaskId taskId, OutputBufferId bufferId, long token, HttpServletRequest request, HttpServletResponse response) throws IOException {
DataSize maxSize = DataSize.valueOf(request.getHeader(PRESTO_MAX_SIZE));
AsyncContext asyncContext = request.startAsync(request, response);
// wait time to get results
Duration waitTime = randomizeWaitTime(DEFAULT_MAX_WAIT_TIME);
asyncContext.setTimeout(waitTime.toMillis() + pageTransportTimeout.toMillis());
asyncContext.addListener(new AsyncListener() {
public void onComplete(AsyncEvent event) {
}
public void onError(AsyncEvent event) throws IOException {
String errorMessage = format("Server error to process task result request %s : %s", requestURI, event.getThrowable().getMessage());
log.error(event.getThrowable(), errorMessage);
response.sendError(SC_INTERNAL_SERVER_ERROR, errorMessage);
}
public void onStartAsync(AsyncEvent event) {
}
public void onTimeout(AsyncEvent event) throws IOException {
String errorMessage = format("Server timeout to process task result request: %s", requestURI);
log.error(event.getThrowable(), errorMessage);
response.sendError(SC_INTERNAL_SERVER_ERROR, errorMessage);
}
});
ListenableFuture<BufferResult> bufferResultFuture = taskManager.getTaskResults(taskId, bufferId, token, maxSize);
bufferResultFuture = addTimeout(bufferResultFuture, () -> BufferResult.emptyResults(taskManager.getTaskInstanceId(taskId), token, false), waitTime, timeoutExecutor);
ServletOutputStream out = response.getOutputStream();
addCallback(bufferResultFuture, new FutureCallback<BufferResult>() {
@Override
public void onSuccess(BufferResult bufferResult) {
response.setHeader(CONTENT_TYPE, PRESTO_PAGES);
response.setHeader(PRESTO_TASK_INSTANCE_ID, bufferResult.getTaskInstanceId());
response.setHeader(PRESTO_PAGE_TOKEN, String.valueOf(bufferResult.getToken()));
response.setHeader(PRESTO_PAGE_NEXT_TOKEN, String.valueOf(bufferResult.getNextToken()));
response.setHeader(PRESTO_BUFFER_COMPLETE, String.valueOf(bufferResult.isBufferComplete()));
List<SerializedPage> serializedPages = bufferResult.getSerializedPages();
if (serializedPages.isEmpty()) {
response.setStatus(SC_NO_CONTENT);
asyncContext.complete();
} else {
int contentLength = (serializedPages.size() * PAGE_METADATA_SIZE) + serializedPages.stream().mapToInt(SerializedPage::getSizeInBytes).sum();
response.setHeader(CONTENT_LENGTH, String.valueOf(contentLength));
out.setWriteListener(new SerializedPageWriteListener(serializedPages, asyncContext, out));
}
}
@Override
public void onFailure(Throwable thrown) {
String errorMessage = format("Error getting task result from TaskManager for request %s : %s", requestURI, thrown.getMessage());
log.error(thrown, errorMessage);
try {
response.sendError(SC_INTERNAL_SERVER_ERROR, errorMessage);
} catch (IOException e) {
log.error(e, "Failed to send response with error code: %s", e.getMessage());
}
asyncContext.complete();
}
}, responseExecutor);
}
use of javax.servlet.AsyncListener in project pinpoint by naver.
the class RequestStartAsyncInterceptor method doInAfterTrace.
@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
if (validate(target, result, throwable)) {
// Add async listener. Servlet 3.0
final AsyncContext asyncContext = (AsyncContext) result;
final AsyncListener asyncListener = new JbossAsyncListener(this.traceContext, recorder.recordNextAsyncContext(true));
asyncContext.addListener(asyncListener);
if (isDebug) {
logger.debug("Add async listener {}", asyncListener);
}
}
recorder.recordServiceType(JbossConstants.JBOSS_METHOD);
recorder.recordApi(methodDescriptor);
recorder.recordException(throwable);
}
use of javax.servlet.AsyncListener in project pinpoint by naver.
the class HttpServletRequestImplInterceptor method doInAfterTrace.
@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
if (validate(target, result, throwable)) {
final AsyncContext asyncContext = (AsyncContext) result;
final AsyncListener asyncListener = new ResinAsyncListener(this.traceContext, recorder.recordNextAsyncContext(true));
asyncContext.addListener(asyncListener);
if (isDebug) {
logger.debug("Add async listener {}", asyncListener);
}
}
recorder.recordServiceType(ResinConstants.RESIN_METHOD);
recorder.recordApi(methodDescriptor);
recorder.recordException(throwable);
}
use of javax.servlet.AsyncListener in project pinpoint by naver.
the class WCCRequestImplStartAsyncInterceptor method doInAfterTrace.
@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
if (validate(target, result, throwable)) {
final AsyncContext asyncContext = (AsyncContext) result;
final AsyncListener asyncListener = new WebsphereAsyncListener(this.traceContext, recorder.recordNextAsyncContext(true));
asyncContext.addListener(asyncListener);
if (isDebug) {
logger.debug("Add async listener {}", asyncListener);
}
}
recorder.recordServiceType(WebsphereConstants.WEBSPHERE_METHOD);
recorder.recordApi(methodDescriptor);
recorder.recordException(throwable);
}
Aggregations