Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 7C916200BC1 for ; Wed, 16 Nov 2016 23:52:10 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 7B8A9160B08; Wed, 16 Nov 2016 22:52:10 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 78B50160B02 for ; Wed, 16 Nov 2016 23:52:09 +0100 (CET) Received: (qmail 22471 invoked by uid 500); 16 Nov 2016 22:52:08 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 22462 invoked by uid 99); 16 Nov 2016 22:52:08 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Nov 2016 22:52:08 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 92944E0209; Wed, 16 Nov 2016 22:52:08 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Message-Id: <54051e704f7441779c21b84cd7920dbc@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cxf git commit: [CXF-7140] Ensure AsyncResponse.cancel(...) behaves the same when invoked twice, patch from Andy McCright applied, This closes #202 Date: Wed, 16 Nov 2016 22:52:08 +0000 (UTC) archived-at: Wed, 16 Nov 2016 22:52:10 -0000 Repository: cxf Updated Branches: refs/heads/3.1.x-fixes 606c55e68 -> 3d9afadeb [CXF-7140] Ensure AsyncResponse.cancel(...) behaves the same when invoked twice, patch from Andy McCright applied, This closes #202 Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/3d9afade Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/3d9afade Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/3d9afade Branch: refs/heads/3.1.x-fixes Commit: 3d9afadeb34a04d2f5505d184b139eca3fb89a36 Parents: 606c55e Author: Sergey Beryozkin Authored: Wed Nov 16 23:48:13 2016 +0100 Committer: Sergey Beryozkin Committed: Wed Nov 16 23:51:22 2016 +0100 ---------------------------------------------------------------------- .../cxf/jaxrs/impl/AsyncResponseImpl.java | 7 +- .../cxf/jaxrs/impl/AsyncResponseImplTest.java | 162 +++++++++++++++++++ 2 files changed, 166 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/3d9afade/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AsyncResponseImpl.java ---------------------------------------------------------------------- diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AsyncResponseImpl.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AsyncResponseImpl.java index c25f770..f1606c9 100644 --- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AsyncResponseImpl.java +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AsyncResponseImpl.java @@ -116,12 +116,13 @@ public class AsyncResponseImpl implements AsyncResponse, ContinuationCallback { } private boolean doCancel(String retryAfterHeader) { - if (!isSuspended()) { - return false; - } if (cancelled) { return true; } + if (!isSuspended()) { + return false; + } + cancelled = true; ResponseBuilder rb = Response.status(503); if (retryAfterHeader != null) { http://git-wip-us.apache.org/repos/asf/cxf/blob/3d9afade/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/AsyncResponseImplTest.java ---------------------------------------------------------------------- diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/AsyncResponseImplTest.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/AsyncResponseImplTest.java new file mode 100644 index 0000000..953d3b6 --- /dev/null +++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/AsyncResponseImplTest.java @@ -0,0 +1,162 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.jaxrs.impl; + +import java.util.Date; + +import javax.servlet.AsyncContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.container.AsyncResponse; + +import org.apache.cxf.continuations.ContinuationProvider; +import org.apache.cxf.message.ExchangeImpl; +import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageImpl; +import org.apache.cxf.transport.http.Servlet3ContinuationProvider; +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class AsyncResponseImplTest extends Assert { + + private IMocksControl control; + + @Before + public void setUp() { + control = EasyMock.createNiceControl(); + } + + /** + * According to the spec, subsequent calls to cancel the same AsyncResponse should + * have the same behavior as the first call. + */ + @Test + public void testCancelBehavesTheSameWhenInvokedMultipleTimes() { + HttpServletRequest req = control.createMock(HttpServletRequest.class); + HttpServletResponse resp = control.createMock(HttpServletResponse.class); + AsyncContext asyncCtx = control.createMock(AsyncContext.class); + Message msg = new MessageImpl(); + msg.setExchange(new ExchangeImpl()); + msg.put(ContinuationProvider.class.getName(), new Servlet3ContinuationProvider(req, resp, msg)); + + req.startAsync(); + EasyMock.expectLastCall().andReturn(asyncCtx); + control.replay(); + + AsyncResponse impl = new AsyncResponseImpl(msg); + + // cancel the AsyncResponse for the first time + assertTrue("Unexpectedly returned false when canceling the first time", impl.cancel()); + + // check the state of the AsyncResponse + assertTrue("AsyncResponse was canceled but is reporting that it was not canceled", impl.isCancelled()); + boolean isDone = impl.isDone(); + boolean isSuspended = impl.isSuspended(); + + // cancel the AsyncResponse a second time + assertTrue("Unexpectedly returned false when canceling the second time", impl.cancel()); + + // verify that the state is the same as before the second cancel + assertTrue("AsyncResponse was canceled (twice) but is reporting that it was not canceled", impl.isCancelled()); + assertEquals("AsynchResponse.isDone() returned a different response after canceling a second time", + isDone, impl.isDone()); + assertEquals("AsynchResponse.isSuspended() returned a different response after canceling a second time", + isSuspended, impl.isSuspended()); + } + + /** + * Similar to testCancelBehavesTheSameWhenInvokedMultipleTimes, but using the cancel(int) signature. + */ + @Test + public void testCancelIntBehavesTheSameWhenInvokedMultipleTimes() { + HttpServletRequest req = control.createMock(HttpServletRequest.class); + HttpServletResponse resp = control.createMock(HttpServletResponse.class); + AsyncContext asyncCtx = control.createMock(AsyncContext.class); + Message msg = new MessageImpl(); + msg.setExchange(new ExchangeImpl()); + msg.put(ContinuationProvider.class.getName(), new Servlet3ContinuationProvider(req, resp, msg)); + + req.startAsync(); + EasyMock.expectLastCall().andReturn(asyncCtx); + control.replay(); + + AsyncResponse impl = new AsyncResponseImpl(msg); + + // cancel the AsyncResponse for the first time + assertTrue("Unexpectedly returned false when canceling the first time", impl.cancel(10)); + + // check the state of the AsyncResponse + assertTrue("AsyncResponse was canceled but is reporting that it was not canceled", impl.isCancelled()); + boolean isDone = impl.isDone(); + boolean isSuspended = impl.isSuspended(); + + // cancel the AsyncResponse a second time + assertTrue("Unexpectedly returned false when canceling the second time", impl.cancel(25)); + + // verify that the state is the same as before the second cancel + assertTrue("AsyncResponse was canceled (twice) but is reporting that it was not canceled", impl.isCancelled()); + assertEquals("AsynchResponse.isDone() returned a different response after canceling a second time", + isDone, impl.isDone()); + assertEquals("AsynchResponse.isSuspended() returned a different response after canceling a second time", + isSuspended, impl.isSuspended()); + } + + /** + * Similar to testCancelBehavesTheSameWhenInvokedMultipleTimes, but using the cancel(Date) signature. + */ + @Test + public void testCancelDateBehavesTheSameWhenInvokedMultipleTimes() { + HttpServletRequest req = control.createMock(HttpServletRequest.class); + HttpServletResponse resp = control.createMock(HttpServletResponse.class); + AsyncContext asyncCtx = control.createMock(AsyncContext.class); + Message msg = new MessageImpl(); + msg.setExchange(new ExchangeImpl()); + msg.put(ContinuationProvider.class.getName(), new Servlet3ContinuationProvider(req, resp, msg)); + + req.startAsync(); + EasyMock.expectLastCall().andReturn(asyncCtx); + control.replay(); + + AsyncResponse impl = new AsyncResponseImpl(msg); + + // cancel the AsyncResponse for the first time + Date d = new Date(System.currentTimeMillis() + 60000); + assertTrue("Unexpectedly returned false when canceling the first time", impl.cancel(d)); + + // check the state of the AsyncResponse + assertTrue("AsyncResponse was canceled but is reporting that it was not canceled", impl.isCancelled()); + boolean isDone = impl.isDone(); + boolean isSuspended = impl.isSuspended(); + + // cancel the AsyncResponse a second time + d = new Date(System.currentTimeMillis() + 120000); + assertTrue("Unexpectedly returned false when canceling the second time", impl.cancel(d)); + + // verify that the state is the same as before the second cancel + assertTrue("AsyncResponse was canceled (twice) but is reporting that it was not canceled", impl.isCancelled()); + assertEquals("AsynchResponse.isDone() returned a different response after canceling a second time", + isDone, impl.isDone()); + assertEquals("AsynchResponse.isSuspended() returned a different response after canceling a second time", + isSuspended, impl.isSuspended()); + } +}