Search in sources :

Example 1 with WriteListener

use of jakarta.servlet.WriteListener in project atmosphere by Atmosphere.

the class SSEAtmosphereInterceptorTest method testDataWriter.

@Test
public void testDataWriter() throws Exception {
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ServletResponse resp = Mockito.mock(HttpServletResponse.class);
    Mockito.when(resp.getOutputStream()).thenReturn(new ServletOutputStream() {

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setWriteListener(WriteListener writeListener) {
        }

        @Override
        public void write(int b) throws IOException {
            baos.write(b);
        }

        @Override
        public void write(byte[] b) throws IOException {
            baos.write(b);
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            baos.write(b, off, len);
        }
    });
    AtmosphereRequest request = AtmosphereRequestImpl.newInstance();
    request.header(HeaderConfig.X_ATMOSPHERE_TRANSPORT, "SSE");
    AtmosphereResponse response = AtmosphereResponseImpl.newInstance(request);
    response.request(request);
    response.setResponse(resp);
    AtmosphereResourceImpl resource = new AtmosphereResourceImpl();
    resource.initialize(framework.getAtmosphereConfig(), framework.getBroadcasterFactory().get(), request, response, Mockito.mock(AsyncSupport.class), null);
    resource.suspend();
    SSEAtmosphereInterceptor interceptor = new SSEAtmosphereInterceptor();
    interceptor.configure(config);
    interceptor.inspect(resource);
    // no newline
    response.write("Good Morning".getBytes());
    assertEquals(baos.toString(), "data:Good Morning\r\n\r\n");
    baos.reset();
    // \n
    response.write("Hello World!\nHave a nice day!".getBytes());
    assertEquals(baos.toString(), "data:Hello World!\r\ndata:Have a nice day!\r\n\r\n");
    baos.reset();
    // \r
    response.write("Hello World!\rHave a nice day!".getBytes());
    assertEquals(baos.toString(), "data:Hello World!\r\ndata:Have a nice day!\r\n\r\n");
    baos.reset();
    // \r\n
    response.write("Hello World!\r\nHave a nice day!".getBytes());
    assertEquals(baos.toString(), "data:Hello World!\r\ndata:Have a nice day!\r\n\r\n");
}
Also used : ServletResponse(jakarta.servlet.ServletResponse) HttpServletResponse(jakarta.servlet.http.HttpServletResponse) AtmosphereResponse(org.atmosphere.cpr.AtmosphereResponse) ServletOutputStream(jakarta.servlet.ServletOutputStream) AsyncSupport(org.atmosphere.cpr.AsyncSupport) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) AtmosphereRequest(org.atmosphere.cpr.AtmosphereRequest) AtmosphereResourceImpl(org.atmosphere.cpr.AtmosphereResourceImpl) WriteListener(jakarta.servlet.WriteListener) Test(org.testng.annotations.Test)

Example 2 with WriteListener

use of jakarta.servlet.WriteListener in project tomcat by apache.

the class CoyoteAdapter method asyncDispatch.

// -------------------------------------------------------- Adapter Methods
@Override
public boolean asyncDispatch(org.apache.coyote.Request req, org.apache.coyote.Response res, SocketEvent status) throws Exception {
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);
    if (request == null) {
        throw new IllegalStateException(sm.getString("coyoteAdapter.nullRequest"));
    }
    boolean success = true;
    AsyncContextImpl asyncConImpl = request.getAsyncContextInternal();
    req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());
    req.setRequestThread();
    try {
        if (!request.isAsync()) {
            // Error or timeout
            // Lift any suspension (e.g. if sendError() was used by an async
            // request) to allow the response to be written to the client
            response.setSuspended(false);
        }
        if (status == SocketEvent.TIMEOUT) {
            if (!asyncConImpl.timeout()) {
                asyncConImpl.setErrorState(null, false);
            }
        } else if (status == SocketEvent.ERROR) {
            // An I/O error occurred on a non-container thread which means
            // that the socket needs to be closed so set success to false to
            // trigger a close
            success = false;
            Throwable t = (Throwable) req.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
            Context context = request.getContext();
            ClassLoader oldCL = null;
            try {
                oldCL = context.bind(false, null);
                if (req.getReadListener() != null) {
                    req.getReadListener().onError(t);
                }
                if (res.getWriteListener() != null) {
                    res.getWriteListener().onError(t);
                }
                res.action(ActionCode.CLOSE_NOW, t);
                asyncConImpl.setErrorState(t, true);
            } finally {
                context.unbind(false, oldCL);
            }
        }
        // Check to see if non-blocking writes or reads are being used
        if (!request.isAsyncDispatching() && request.isAsync()) {
            WriteListener writeListener = res.getWriteListener();
            ReadListener readListener = req.getReadListener();
            if (writeListener != null && status == SocketEvent.OPEN_WRITE) {
                Context context = request.getContext();
                ClassLoader oldCL = null;
                try {
                    oldCL = context.bind(false, null);
                    res.onWritePossible();
                    if (request.isFinished() && req.sendAllDataReadEvent() && readListener != null) {
                        readListener.onAllDataRead();
                    }
                    // User code may have swallowed an IOException
                    if (response.getCoyoteResponse().isExceptionPresent()) {
                        throw response.getCoyoteResponse().getErrorException();
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    // Need to trigger the call to AbstractProcessor.setErrorState()
                    // before the listener is called so the listener can call complete
                    // Therefore no need to set success=false as that would trigger a
                    // second call to AbstractProcessor.setErrorState()
                    // https://bz.apache.org/bugzilla/show_bug.cgi?id=65001
                    writeListener.onError(t);
                    res.action(ActionCode.CLOSE_NOW, t);
                    asyncConImpl.setErrorState(t, true);
                } finally {
                    context.unbind(false, oldCL);
                }
            } else if (readListener != null && status == SocketEvent.OPEN_READ) {
                Context context = request.getContext();
                ClassLoader oldCL = null;
                try {
                    oldCL = context.bind(false, null);
                    // onDataAvailable() is not called in this case.
                    if (!request.isFinished()) {
                        req.onDataAvailable();
                    }
                    if (request.isFinished() && req.sendAllDataReadEvent()) {
                        readListener.onAllDataRead();
                    }
                    // User code may have swallowed an IOException
                    if (request.getCoyoteRequest().isExceptionPresent()) {
                        throw request.getCoyoteRequest().getErrorException();
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    // Need to trigger the call to AbstractProcessor.setErrorState()
                    // before the listener is called so the listener can call complete
                    // Therefore no need to set success=false as that would trigger a
                    // second call to AbstractProcessor.setErrorState()
                    // https://bz.apache.org/bugzilla/show_bug.cgi?id=65001
                    readListener.onError(t);
                    res.action(ActionCode.CLOSE_NOW, t);
                    asyncConImpl.setErrorState(t, true);
                } finally {
                    context.unbind(false, oldCL);
                }
            }
        }
        // if the application doesn't define one)?
        if (!request.isAsyncDispatching() && request.isAsync() && response.isErrorReportRequired()) {
            connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
        }
        if (request.isAsyncDispatching()) {
            connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
            Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
            if (t != null) {
                asyncConImpl.setErrorState(t, true);
            }
        }
        if (!request.isAsync()) {
            request.finishRequest();
            response.finishResponse();
        }
        // Check to see if the processor is in an error state. If it is,
        // bail out now.
        AtomicBoolean error = new AtomicBoolean(false);
        res.action(ActionCode.IS_ERROR, error);
        if (error.get()) {
            if (request.isAsyncCompleting()) {
                // Connection will be forcibly closed which will prevent
                // completion happening at the usual point. Need to trigger
                // call to onComplete() here.
                res.action(ActionCode.ASYNC_POST_PROCESS, null);
            }
            success = false;
        }
    } catch (IOException e) {
        success = false;
    // Ignore
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        success = false;
        log.error(sm.getString("coyoteAdapter.asyncDispatch"), t);
    } finally {
        if (!success) {
            res.setStatus(500);
        }
        // Access logging
        if (!success || !request.isAsync()) {
            long time = 0;
            if (req.getStartTimeNanos() != -1) {
                time = System.nanoTime() - req.getStartTimeNanos();
            }
            Context context = request.getContext();
            if (context != null) {
                context.logAccess(request, response, time, false);
            } else {
                log(req, res, time);
            }
        }
        req.getRequestProcessor().setWorkerThreadName(null);
        // Recycle the wrapper request and response
        if (!success || !request.isAsync()) {
            updateWrapperErrorCount(request, response);
            request.recycle();
            response.recycle();
        }
    }
    return success;
}
Also used : Context(org.apache.catalina.Context) AsyncContextImpl(org.apache.catalina.core.AsyncContextImpl) IOException(java.io.IOException) ReadListener(jakarta.servlet.ReadListener) HttpServletResponse(jakarta.servlet.http.HttpServletResponse) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) WriteListener(jakarta.servlet.WriteListener)

Aggregations

WriteListener (jakarta.servlet.WriteListener)2 HttpServletResponse (jakarta.servlet.http.HttpServletResponse)2 IOException (java.io.IOException)2 ReadListener (jakarta.servlet.ReadListener)1 ServletOutputStream (jakarta.servlet.ServletOutputStream)1 ServletResponse (jakarta.servlet.ServletResponse)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Context (org.apache.catalina.Context)1 AsyncContextImpl (org.apache.catalina.core.AsyncContextImpl)1 AsyncSupport (org.atmosphere.cpr.AsyncSupport)1 AtmosphereRequest (org.atmosphere.cpr.AtmosphereRequest)1 AtmosphereResourceImpl (org.atmosphere.cpr.AtmosphereResourceImpl)1 AtmosphereResponse (org.atmosphere.cpr.AtmosphereResponse)1 Test (org.testng.annotations.Test)1