Context ctxt = tomcat.addContext("", null); // This is the target of the HTTP/2 upgrade request
Tomcat.addServlet(ctxt, "simple", new SimpleServlet());
ctxt.addServletMappingDecoded("/simple", "simple");
// This is the servlet that does that actual test // This latch is used to signal that that async thread used by the test // has ended. It isn't essential to the test but it allows the test to // complete without Tomcat logging an error about a still running thread.
CountDownLatch latch = new CountDownLatch(1);
Wrapper w = Tomcat.addServlet(ctxt, "async", new AsyncTimeoutServlet(latch));
w.setAsyncSupported(true);
ctxt.addServletMappingDecoded("/async", "async");
tomcat.start();
// The idea of this test is that the timeout kicks in after 2 // seconds and stops the async thread early rather than letting it // complete the full 5 seconds of processing. final AsyncContext asyncContext = request.startAsync();
// Only want to call complete() once (else we get stack traces in // the logs so use this to track when complete() is called).
AtomicBoolean completeCalled = new AtomicBoolean(false);
Ticker ticker = new Ticker(asyncContext, completeCalled);
TimeoutListener listener = new TimeoutListener(latch, ticker, completeCalled);
asyncContext.addListener(listener);
asyncContext.setTimeout(2000);
ticker.start();
}
}
// If the test works running will be set to false before // counter reaches 50. while (running && counter < 50) {
sleep(100);
counter++;
pw.print("Tick " + counter);
} // Need to call complete() here if the test fails but complete() // should have been called by the listener. Use the flag to make // sure we only call complete once. if (completeCalled.compareAndSet(false, true)) {
asyncContext.complete();
}
} catch (IOException | InterruptedException e) { // Ignore
}
}
}
@Override publicvoid onTimeout(AsyncEvent event) throws IOException {
ticker.end(); // Wait for the ticker to exit to avoid concurrent access to the // response and associated writer. // Excessively long timeout just in case things so wrong so test // does not lock up. try {
ticker.join(10 * 1000);
} catch (InterruptedException e) { thrownew IOException(e);
}
if (ended.compareAndSet(false, true)) {
PrintWriter pw = event.getAsyncContext().getResponse().getWriter();
pw.write("PASS");
pw.flush(); // If the timeout fires we should always need to call complete() // here but use the flag to be safe. if (completeCalled.compareAndSet(false, true)) {
event.getAsyncContext().complete();
}
}
}
@Override publicvoid onComplete(AsyncEvent event) throws IOException { if (ended.compareAndSet(false, true)) {
PrintWriter pw = event.getAsyncContext().getResponse().getWriter();
pw.write("FAIL");
pw.flush();
} try { // Wait for the async thread to end before we signal that the // test is complete. This avoids logging an exception about a // still running thread when the unit test shuts down.
ticker.join();
latch.countDown();
} catch (InterruptedException e) { // Ignore
}
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.