You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/03/06 16:59:04 UTC
svn commit: r1574937 - in /tomcat/tc7.0.x/trunk: ./
java/org/apache/catalina/core/ java/org/apache/coyote/
test/org/apache/catalina/core/ webapps/docs/
Author: markt
Date: Thu Mar 6 15:59:03 2014
New Revision: 1574937
URL: http://svn.apache.org/r1574937
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56190
AsyncContext.complete() should close the response. dispatch() should be used if further output to the response is required.
Modified:
tomcat/tc7.0.x/trunk/ (props changed)
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncContextCallback.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java
tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java
tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
Merged /tomcat/trunk:r1574923,1574936
Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java?rev=1574937&r1=1574936&r2=1574937&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java Thu Mar 6 15:59:03 2014
@@ -88,12 +88,13 @@ public class AsyncContextImpl implements
logDebug("complete ");
}
check();
- request.getCoyoteRequest().action(ActionCode.COMMIT, null);
request.getCoyoteRequest().action(ActionCode.ASYNC_COMPLETE, null);
}
@Override
- public void fireOnComplete() {
+ public void fireOnComplete() throws IOException {
+ // Before firing the event, close the response
+ request.getResponse().finishResponse();
List<AsyncListenerWrapper> listenersCopy =
new ArrayList<AsyncListenerWrapper>();
listenersCopy.addAll(listeners);
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncContextCallback.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncContextCallback.java?rev=1574937&r1=1574936&r2=1574937&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncContextCallback.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncContextCallback.java Thu Mar 6 15:59:03 2014
@@ -16,6 +16,8 @@
*/
package org.apache.coyote;
+import java.io.IOException;
+
/**
* Provides a mechanism for the Coyote connectors to signal to a
* {@link javax.servlet.AsyncContext} implementation that an action, such as
@@ -24,5 +26,5 @@ package org.apache.coyote;
* org.apache.coyote package.
*/
public interface AsyncContextCallback {
- public void fireOnComplete();
+ public void fireOnComplete() throws IOException;
}
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java?rev=1574937&r1=1574936&r2=1574937&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/AsyncStateMachine.java Thu Mar 6 15:59:03 2014
@@ -16,6 +16,7 @@
*/
package org.apache.coyote;
+import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -187,11 +188,21 @@ public class AsyncStateMachine<S> {
state = AsyncState.STARTED;
return SocketState.LONG;
} else if (state == AsyncState.MUST_COMPLETE) {
- asyncCtxt.fireOnComplete();
+ try {
+ asyncCtxt.fireOnComplete();
+ } catch (IOException e) {
+ // Socket is in unknown state. Close it.
+ return SocketState.CLOSED;
+ }
state = AsyncState.DISPATCHED;
return SocketState.ASYNC_END;
} else if (state == AsyncState.COMPLETING) {
- asyncCtxt.fireOnComplete();
+ try {
+ asyncCtxt.fireOnComplete();
+ } catch (IOException e) {
+ // Socket is in unknown state. Close it.
+ return SocketState.CLOSED;
+ }
state = AsyncState.DISPATCHED;
return SocketState.ASYNC_END;
} else if (state == AsyncState.MUST_DISPATCH) {
Modified: tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java?rev=1574937&r1=1574936&r2=1574937&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java (original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java Thu Mar 6 15:59:03 2014
@@ -14,12 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.catalina.core;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -46,12 +46,12 @@ import javax.servlet.http.HttpServletRes
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+
import org.junit.Assert;
import org.junit.Test;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
-import org.apache.catalina.connector.Request;
import org.apache.catalina.deploy.ApplicationListener;
import org.apache.catalina.deploy.ErrorPage;
import org.apache.catalina.startup.Tomcat;
@@ -68,6 +68,20 @@ public class TestAsyncContextImpl extend
// Default timeout for these tests
private static final long TIMEOUT = 3000;
+ private static StringBuilder tracker;
+
+ public static synchronized void resetTracker() {
+ tracker = new StringBuilder();
+ }
+
+ public static synchronized void track(String trace) {
+ tracker.append(trace);
+ }
+
+ public static synchronized String getTrack() {
+ return tracker.toString();
+ }
+
@Test
public void testBug49528() throws Exception {
// Setup Tomcat instance
@@ -146,6 +160,7 @@ public class TestAsyncContextImpl extend
@Test
public void testAsyncStartNoComplete() throws Exception {
+ resetTracker();
// Setup Tomcat instance
Tomcat tomcat = getTomcatInstance();
@@ -170,14 +185,16 @@ public class TestAsyncContextImpl extend
tomcat.start();
// Call the servlet the first time
- ByteChunk bc1 = getUrl("http://localhost:" + getPort() +
- "/?echo=run1");
- assertEquals("OK-run1", bc1.toString());
+ getUrl("http://localhost:" + getPort() + "/?echo=run1");
+ Assert.assertEquals("OK-run1", getTrack());
+ resetTracker();
// Call the servlet the second time with a request parameter
- ByteChunk bc2 = getUrl("http://localhost:" + getPort() +
- "/?echo=run2");
- assertEquals("OK-run2", bc2.toString());
+ getUrl("http://localhost:" + getPort() + "/?echo=run2");
+ Assert.assertEquals("OK-run2", getTrack());
+
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
// Check the access log
alv.validateAccessLog(2, 500,
@@ -208,8 +225,15 @@ public class TestAsyncContextImpl extend
tomcat.start();
// Call the servlet once
- ByteChunk bc = getUrl("http://localhost:" + getPort() + "/");
+ ByteChunk bc = new ByteChunk();
+ Map<String,List<String>> headers = new HashMap<String,List<String>>();
+ getUrl("http://localhost:" + getPort() + "/", bc, headers);
+
assertEquals("OK", bc.toString());
+ List<String> contentLength = headers.get("Content-Length");
+ Assert.assertNotNull(contentLength);
+ Assert.assertEquals(1, contentLength.size());
+ Assert.assertEquals("2", contentLength.get(0));
// Check the access log
alv.validateAccessLog(1, 200, 0, REQUEST_TIME);
@@ -356,10 +380,9 @@ public class TestAsyncContextImpl extend
String echo = req.getParameter("echo");
AsyncContext actxt = req.startAsync();
- resp.setContentType("text/plain");
- resp.getWriter().print("OK");
+ TestAsyncContextImpl.track("OK");
if (echo != null) {
- resp.getWriter().print("-" + echo);
+ TestAsyncContextImpl.track("-" + echo);
}
// Speed up the test by reducing the timeout
actxt.setTimeout(ASYNC_TIMEOUT);
@@ -429,6 +452,8 @@ public class TestAsyncContextImpl extend
private void doTestTimeout(Boolean completeOnTimeout, Boolean asyncDispatch)
throws Exception {
+ resetTracker();
+
String dispatchUrl = null;
if (asyncDispatch != null) {
if (asyncDispatch.booleanValue()) {
@@ -477,9 +502,8 @@ public class TestAsyncContextImpl extend
tomcat.getHost().getPipeline().addValve(alvGlobal);
tomcat.start();
- ByteChunk res = new ByteChunk();
try {
- getUrl("http://localhost:" + getPort() + "/start", res, null);
+ getUrl("http://localhost:" + getPort() + "/start");
} catch (IOException ioe) {
// Ignore - expected for some error conditions
}
@@ -503,10 +527,19 @@ public class TestAsyncContextImpl extend
expected.append("onComplete-");
expected.append("requestDestroyed");
}
- assertEquals(expected.toString(), res.toString());
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
+ String expectedTrack = expected.toString();
+ int count = 0;
+ while (!expectedTrack.equals(getTrack()) && count < 100) {
+ Thread.sleep(50);
+ count ++;
+ }
+ assertEquals(expectedTrack, getTrack());
// Check the access log
- if (completeOnTimeout == null) {
+ if (completeOnTimeout == null ||
+ (!completeOnTimeout.booleanValue() && asyncDispatch == null)) {
alvGlobal.validateAccessLog(1, 500, TimeoutServlet.ASYNC_TIMEOUT,
TimeoutServlet.ASYNC_TIMEOUT + TIMEOUT_MARGIN +
REQUEST_TIME);
@@ -544,7 +577,7 @@ public class TestAsyncContextImpl extend
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (req.isAsyncSupported()) {
- resp.getWriter().print("TimeoutServletGet-");
+ TestAsyncContextImpl.track("TimeoutServletGet-");
final AsyncContext ac = req.startAsync();
ac.setTimeout(ASYNC_TIMEOUT);
@@ -589,6 +622,7 @@ public class TestAsyncContextImpl extend
}
private void doTestDispatch(int iter, boolean useThread) throws Exception {
+ resetTracker();
// Setup Tomcat instance
Tomcat tomcat = getTomcatInstance();
@@ -623,7 +657,7 @@ public class TestAsyncContextImpl extend
if (useThread) {
url.append("&useThread=y");
}
- ByteChunk res = getUrl(url.toString());
+ getUrl(url.toString());
StringBuilder expected = new StringBuilder("requestInitialized-");
int loop = iter;
@@ -633,7 +667,15 @@ public class TestAsyncContextImpl extend
}
expected.append("NonAsyncServletGet-");
expected.append("requestDestroyed");
- assertEquals(expected.toString(), res.toString());
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
+ String expectedTrack = expected.toString();
+ int count = 0;
+ while (!expectedTrack.equals(getTrack()) && count < 100) {
+ Thread.sleep(50);
+ count ++;
+ }
+ assertEquals(expectedTrack, getTrack());
// Check the access log
alv.validateAccessLog(1, 200, 0, REQUEST_TIME);
@@ -659,11 +701,10 @@ public class TestAsyncContextImpl extend
if ("y".equals(req.getParameter(DISPATCH_CHECK))) {
if (req.getDispatcherType() != DispatcherType.ASYNC) {
- resp.getWriter().write("WrongDispatcherType-");
+ track("WrongDispatcherType-");
}
}
- resp.getWriter().write("DispatchingServletGet-");
- resp.flushBuffer();
+ track("DispatchingServletGet-");
final int iter = Integer.parseInt(req.getParameter(ITER_PARAM)) - 1;
final AsyncContext ctxt = req.startAsync();
if (addTrackingListener) {
@@ -697,13 +738,13 @@ public class TestAsyncContextImpl extend
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
- resp.getWriter().write("NonAsyncServletGet-");
- resp.flushBuffer();
+ TestAsyncContextImpl.track("NonAsyncServletGet-");
}
}
@Test
public void testListeners() throws Exception {
+ resetTracker();
// Setup Tomcat instance
Tomcat tomcat = getTomcatInstance();
@@ -732,12 +773,19 @@ public class TestAsyncContextImpl extend
url.append(getPort());
url.append("/stage1");
- ByteChunk res = getUrl(url.toString());
+ getUrl(url.toString());
- assertEquals(
- "DispatchingServletGet-DispatchingServletGet-onStartAsync-" +
- "TimeoutServletGet-onStartAsync-onTimeout-onComplete-",
- res.toString());
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
+ String expectedTrack = "DispatchingServletGet-DispatchingServletGet-" +
+ "onStartAsync-TimeoutServletGet-onStartAsync-onTimeout-" +
+ "onComplete-";
+ int count = 0;
+ while (!expectedTrack.equals(getTrack()) && count < 100) {
+ Thread.sleep(50);
+ count ++;
+ }
+ Assert.assertEquals(expectedTrack, getTrack());
// Check the access log
alv.validateAccessLog(1, 200, TimeoutServlet.ASYNC_TIMEOUT,
@@ -753,7 +801,7 @@ public class TestAsyncContextImpl extend
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
- resp.getWriter().write("DispatchingServletGet-");
+ TestAsyncContextImpl.track("DispatchingServletGet-");
resp.flushBuffer();
final boolean first = TrackingServlet.first;
@@ -797,16 +845,12 @@ public class TestAsyncContextImpl extend
@Override
public void onComplete(AsyncEvent event) throws IOException {
- ServletResponse resp = event.getAsyncContext().getResponse();
- resp.getWriter().write("onComplete-");
- resp.flushBuffer();
+ TestAsyncContextImpl.track("onComplete-");
}
@Override
public void onTimeout(AsyncEvent event) throws IOException {
- ServletResponse resp = event.getAsyncContext().getResponse();
- resp.getWriter().write("onTimeout-");
- resp.flushBuffer();
+ TestAsyncContextImpl.track("onTimeout-");
if (completeOnTimeout){
event.getAsyncContext().complete();
}
@@ -817,9 +861,7 @@ public class TestAsyncContextImpl extend
@Override
public void onError(AsyncEvent event) throws IOException {
- ServletResponse resp = event.getAsyncContext().getResponse();
- resp.getWriter().write("onError-");
- resp.flushBuffer();
+ TestAsyncContextImpl.track("onError-");
if (completeOnError) {
event.getAsyncContext().complete();
}
@@ -827,9 +869,7 @@ public class TestAsyncContextImpl extend
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
- ServletResponse resp = event.getAsyncContext().getResponse();
- resp.getWriter().write("onStartAsync-");
- resp.flushBuffer();
+ TestAsyncContextImpl.track("onStartAsync-");
}
}
@@ -838,26 +878,12 @@ public class TestAsyncContextImpl extend
@Override
public void requestDestroyed(ServletRequestEvent sre) {
- // Need the response and it isn't available via the Servlet API
- Request r = (Request) sre.getServletRequest();
- try {
- r.getResponse().getWriter().print("requestDestroyed");
- } catch (IOException e) {
- // Test will fail if this happens
- e.printStackTrace();
- }
+ TestAsyncContextImpl.track("requestDestroyed");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
- // Need the response and it isn't available via the Servlet API
- Request r = (Request) sre.getServletRequest();
- try {
- r.getResponse().getWriter().print("requestInitialized-");
- } catch (IOException e) {
- // Test will fail if this happens
- e.printStackTrace();
- }
+ TestAsyncContextImpl.track("requestInitialized-");
}
}
@@ -927,6 +953,7 @@ public class TestAsyncContextImpl extend
private void doTestDispatchError(int iter, boolean useThread,
boolean completeOnError)
throws Exception {
+ resetTracker();
// Setup Tomcat instance
Tomcat tomcat = getTomcatInstance();
@@ -941,7 +968,7 @@ public class TestAsyncContextImpl extend
wrapper.setAsyncSupported(true);
ctx.addServletMapping("/stage1", "dispatch");
- ErrorServlet error = new ErrorServlet(true);
+ ErrorServlet error = new ErrorServlet();
Tomcat.addServlet(ctx, "error", error);
ctx.addServletMapping("/stage2", "error");
@@ -961,7 +988,7 @@ public class TestAsyncContextImpl extend
if (useThread) {
url.append("&useThread=y");
}
- ByteChunk res = getUrl(url.toString());
+ getUrl(url.toString());
StringBuilder expected = new StringBuilder("requestInitialized-");
int loop = iter;
@@ -973,29 +1000,28 @@ public class TestAsyncContextImpl extend
loop--;
}
expected.append("ErrorServletGet-onError-onComplete-requestDestroyed");
- assertEquals(expected.toString(), res.toString());
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
+ String expectedTrack = expected.toString();
+ int count = 0;
+ while (!expectedTrack.equals(getTrack()) && count < 100) {
+ Thread.sleep(50);
+ count ++;
+ }
+ assertEquals(expectedTrack, getTrack());
// Check the access log
- alv.validateAccessLog(1, 200, 0, REQUEST_TIME);
+ alv.validateAccessLog(1, 500, 0, REQUEST_TIME);
}
private static class ErrorServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
- private boolean flush = false;
-
- public ErrorServlet(boolean flush) {
- this.flush = flush;
- }
-
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
- resp.getWriter().write("ErrorServletGet-");
- if (flush) {
- resp.flushBuffer();
- }
+ TestAsyncContextImpl.track("ErrorServletGet-");
try {
// Give the original thread a chance to exit the
// ErrorReportValve before we throw this exception
@@ -1009,6 +1035,7 @@ public class TestAsyncContextImpl extend
@Test
public void testBug50352() throws Exception {
+ resetTracker();
// Setup Tomcat instance
Tomcat tomcat = getTomcatInstance();
@@ -1027,9 +1054,17 @@ public class TestAsyncContextImpl extend
tomcat.start();
- ByteChunk res = getUrl("http://localhost:" + getPort() + "/");
+ getUrl("http://localhost:" + getPort() + "/");
- assertEquals("Runnable-onComplete-", res.toString());
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
+ String expectedTrack = "Runnable-onComplete-";
+ int count = 0;
+ while (!expectedTrack.equals(getTrack()) && count < 100) {
+ Thread.sleep(50);
+ count ++;
+ }
+ assertEquals(expectedTrack, getTrack());
// Check the access log
alv.validateAccessLog(1, 200, AsyncStartRunnable.THREAD_SLEEP_TIME,
@@ -1058,8 +1093,7 @@ public class TestAsyncContextImpl extend
public void run() {
try {
Thread.sleep(THREAD_SLEEP_TIME);
- asyncContext.getResponse().getWriter().write(
- "Runnable-");
+ TestAsyncContextImpl.track("Runnable-");
asyncContext.complete();
} catch (Exception e) {
e.printStackTrace();
@@ -1145,7 +1179,7 @@ public class TestAsyncContextImpl extend
Context ctx = tomcat.addContext("", docBase.getAbsolutePath());
- ErrorServlet error = new ErrorServlet(false);
+ ErrorServlet error = new ErrorServlet();
Tomcat.addServlet(ctx, "error", error);
ctx.addServletMapping("/error", "error");
@@ -1529,6 +1563,7 @@ public class TestAsyncContextImpl extend
private void doTestTimeoutErrorDispatch(Boolean asyncError,
ErrorPageAsyncMode mode) throws Exception {
+ resetTracker();
// Setup Tomcat instance
Tomcat tomcat = getTomcatInstance();
@@ -1581,12 +1616,7 @@ public class TestAsyncContextImpl extend
}
StringBuilder expected = new StringBuilder();
- if (asyncError == null) {
- // No error handler - just get the 500 response
- expected.append("requestInitialized-TimeoutServletGet-");
- // Note: With an error handler the response will be reset and these
- // will be lost
- }
+ expected.append("requestInitialized-TimeoutServletGet-");
if (asyncError != null) {
if (asyncError.booleanValue()) {
expected.append("AsyncErrorPageGet-");
@@ -1603,7 +1633,15 @@ public class TestAsyncContextImpl extend
}
expected.append("requestDestroyed");
- Assert.assertEquals(expected.toString(), res.toString());
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
+ String expectedTrack = expected.toString();
+ int count = 0;
+ while (!expectedTrack.equals(getTrack()) && count < 100) {
+ Thread.sleep(50);
+ count ++;
+ }
+ Assert.assertEquals(expectedTrack, getTrack());
// Check the access log
alvGlobal.validateAccessLog(1, 500, TimeoutServlet.ASYNC_TIMEOUT,
@@ -1633,23 +1671,21 @@ public class TestAsyncContextImpl extend
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
- PrintWriter writer = resp.getWriter();
- writer.write("AsyncErrorPageGet-");
- resp.flushBuffer();
+ TestAsyncContextImpl.track("AsyncErrorPageGet-");
final AsyncContext ctxt = req.getAsyncContext();
switch(mode) {
case COMPLETE:
- writer.write("Complete-");
+ TestAsyncContextImpl.track("Complete-");
ctxt.complete();
break;
case DISPATCH:
- writer.write("Dispatch-");
+ TestAsyncContextImpl.track("Dispatch-");
ctxt.dispatch("/error/nonasync");
break;
case NO_COMPLETE:
- writer.write("NoOp-");
+ TestAsyncContextImpl.track("NoOp-");
break;
default:
// Impossible
@@ -1764,6 +1800,7 @@ public class TestAsyncContextImpl extend
@Test
public void testForbiddenDispatching() throws Exception {
+ resetTracker();
// Setup Tomcat instance
Tomcat tomcat = getTomcatInstance();
@@ -1787,19 +1824,24 @@ public class TestAsyncContextImpl extend
tomcat.start();
- ByteChunk body = new ByteChunk();
-
try {
getUrl("http://localhost:" + getPort()
- + "/forbiddenDispatchingServlet", body, null);
+ + "/forbiddenDispatchingServlet");
} catch (IOException ioe) {
// This may happen if test fails. Output the exception in case it is
// useful and let asserts handle the failure
ioe.printStackTrace();
}
- assertTrue(body.toString().contains("OK"));
- assertTrue(body.toString().contains("NonAsyncServletGet"));
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
+ String expectedTrack = "OKNonAsyncServletGet-";
+ int count = 0;
+ while (!expectedTrack.equals(getTrack()) && count < 100) {
+ Thread.sleep(50);
+ count ++;
+ }
+ Assert.assertEquals(expectedTrack, getTrack());
}
private static class DispatchingGenericServlet extends GenericServlet {
@@ -1827,12 +1869,12 @@ public class TestAsyncContextImpl extend
}
try {
asyncContext.dispatch("/nonExistingServlet");
- resp.getWriter().print("FAIL");
+ TestAsyncContextImpl.track("FAIL");
} catch (IllegalStateException e) {
- resp.getWriter().print("OK");
+ TestAsyncContextImpl.track("OK");
}
} else {
- resp.getWriter().print("DispatchingGenericServletGet-");
+ TestAsyncContextImpl.track("DispatchingGenericServletGet-");
}
}
@@ -1863,7 +1905,7 @@ public class TestAsyncContextImpl extend
throws ServletException, IOException {
if (req instanceof ServletRequestWrapper
&& res instanceof ServletResponseWrapper) {
- res.getWriter().print("CustomGenericServletGet-");
+ TestAsyncContextImpl.track("CustomGenericServletGet-");
}
}
@@ -1935,8 +1977,17 @@ public class TestAsyncContextImpl extend
private void requestApplicationWithGenericServlet(String path,
StringBuilder expectedContent) throws Exception {
- ByteChunk res = getUrl("http://localhost:" + getPort() + path);
+ resetTracker();
+ getUrl("http://localhost:" + getPort() + path);
- assertEquals(expectedContent.toString(), res.toString());
+ // Request may complete before listener has finished processing so wait
+ // up to 5 seconds for the right response
+ String expectedTrack = expectedContent.toString();
+ int count = 0;
+ while (!expectedTrack.equals(getTrack()) && count < 100) {
+ Thread.sleep(50);
+ count ++;
+ }
+ Assert.assertEquals(expectedTrack, getTrack());
}
}
Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1574937&r1=1574936&r2=1574937&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Thu Mar 6 15:59:03 2014
@@ -69,6 +69,11 @@
elements and attributes supported by the Servlet version of the merged
file. (markt)
</fix>
+ <fix>
+ <bug>56190</bug>: The response should be closed (i.e. no further output
+ is permitted) when a call to <code>AsyncContext.complete()</code> takes
+ effect. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org