Skip to content

Commit 4e3ca3f

Browse files
author
Stephane Landelle
committed
execute shouldn't throw Exceptions, close AsyncHttpClient#710
1 parent 1375217 commit 4e3ca3f

File tree

16 files changed

+425
-484
lines changed

16 files changed

+425
-484
lines changed

api/src/main/java/org/asynchttpclient/AsyncHttpClient.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.asynchttpclient;
1818

1919
import java.io.Closeable;
20-
import java.io.IOException;
2120
import java.util.concurrent.Future;
2221

2322
/**
@@ -251,16 +250,14 @@ public interface AsyncHttpClient extends Closeable {
251250
* @param handler an instance of {@link AsyncHandler}
252251
* @param <T> Type of the value that will be returned by the associated {@link java.util.concurrent.Future}
253252
* @return a {@link Future} of type T
254-
* @throws IOException
255253
*/
256-
<T> ListenableFuture<T> executeRequest(Request request, AsyncHandler<T> handler) throws IOException;
254+
<T> ListenableFuture<T> executeRequest(Request request, AsyncHandler<T> handler);
257255

258256
/**
259257
* Execute an HTTP request.
260258
*
261259
* @param request {@link Request}
262260
* @return a {@link Future} of type Response
263-
* @throws IOException
264261
*/
265-
ListenableFuture<Response> executeRequest(Request request) throws IOException;
262+
ListenableFuture<Response> executeRequest(Request request);
266263
}

api/src/main/java/org/asynchttpclient/AsyncHttpProvider.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package org.asynchttpclient;
1717

1818
import java.io.Closeable;
19-
import java.io.IOException;
2019

2120
/**
2221
* Interface to be used when implementing custom asynchronous I/O HTTP client.
@@ -28,9 +27,8 @@ public interface AsyncHttpProvider extends Closeable {
2827
*
2928
* @param handler an instance of {@link AsyncHandler}
3029
* @return a {@link ListenableFuture} of Type T.
31-
* @throws IOException
3230
*/
33-
<T> ListenableFuture<T> execute(Request request, AsyncHandler<T> handler) throws IOException;
31+
<T> ListenableFuture<T> execute(Request request, AsyncHandler<T> handler);
3432

3533
/**
3634
* Close the current underlying TCP/HTTP connection.

api/src/main/java/org/asynchttpclient/BoundRequestBuilder.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import org.asynchttpclient.cookie.Cookie;
1616
import org.asynchttpclient.multipart.Part;
1717

18-
import java.io.IOException;
1918
import java.io.InputStream;
2019
import java.util.Collection;
2120
import java.util.List;
@@ -35,11 +34,11 @@ public BoundRequestBuilder(AsyncHttpClient client, Request prototype) {
3534
this.client = client;
3635
}
3736

38-
public <T> ListenableFuture<T> execute(AsyncHandler<T> handler) throws IOException {
37+
public <T> ListenableFuture<T> execute(AsyncHandler<T> handler) {
3938
return client.executeRequest(build(), handler);
4039
}
4140

42-
public ListenableFuture<Response> execute() throws IOException {
41+
public ListenableFuture<Response> execute() {
4342
return client.executeRequest(build(), new AsyncCompletionHandlerBase());
4443
}
4544

api/src/main/java/org/asynchttpclient/DefaultAsyncHttpClient.java

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,18 @@
1616
*/
1717
package org.asynchttpclient;
1818

19+
import java.lang.reflect.InvocationTargetException;
20+
import java.util.concurrent.ExecutorService;
21+
import java.util.concurrent.Executors;
22+
import java.util.concurrent.atomic.AtomicBoolean;
23+
1924
import org.asynchttpclient.filter.FilterContext;
2025
import org.asynchttpclient.filter.FilterException;
2126
import org.asynchttpclient.filter.RequestFilter;
2227
import org.asynchttpclient.resumable.ResumableAsyncHandler;
2328
import org.slf4j.Logger;
2429
import org.slf4j.LoggerFactory;
2530

26-
import java.io.IOException;
27-
import java.lang.reflect.InvocationTargetException;
28-
import java.util.concurrent.ExecutorService;
29-
import java.util.concurrent.Executors;
30-
import java.util.concurrent.atomic.AtomicBoolean;
31-
3231
public class DefaultAsyncHttpClient implements AsyncHttpClient {
3332

3433
/**
@@ -225,21 +224,26 @@ public BoundRequestBuilder prepareRequest(Request request) {
225224
}
226225

227226
@Override
228-
public <T> ListenableFuture<T> executeRequest(Request request, AsyncHandler<T> handler) throws IOException {
227+
public <T> ListenableFuture<T> executeRequest(Request request, AsyncHandler<T> handler) {
229228

230229
if (config.getRequestFilters().isEmpty()) {
231230
return httpProvider.execute(request, handler);
232231

233232
} else {
234233
FilterContext<T> fc = new FilterContext.FilterContextBuilder<T>().asyncHandler(handler).request(request).build();
235-
fc = preProcessRequest(fc);
234+
try {
235+
fc = preProcessRequest(fc);
236+
} catch (Exception e) {
237+
handler.onThrowable(e);
238+
return new ListenableFuture.CompletedFailure<T>("preProcessRequest failed", e);
239+
}
236240

237241
return httpProvider.execute(fc.getRequest(), fc.getAsyncHandler());
238242
}
239243
}
240244

241245
@Override
242-
public ListenableFuture<Response> executeRequest(Request request) throws IOException {
246+
public ListenableFuture<Response> executeRequest(Request request) {
243247
return executeRequest(request, new AsyncCompletionHandlerBase());
244248
}
245249

@@ -249,17 +253,11 @@ public ListenableFuture<Response> executeRequest(Request request) throws IOExcep
249253
* @param fc {@link FilterContext}
250254
* @return {@link FilterContext}
251255
*/
252-
private <T> FilterContext<T> preProcessRequest(FilterContext<T> fc) throws IOException {
256+
private <T> FilterContext<T> preProcessRequest(FilterContext<T> fc) throws FilterException {
253257
for (RequestFilter asyncFilter : config.getRequestFilters()) {
254-
try {
255-
fc = asyncFilter.filter(fc);
256-
if (fc == null) {
257-
throw new NullPointerException("FilterContext is null");
258-
}
259-
} catch (FilterException e) {
260-
IOException ex = new IOException();
261-
ex.initCause(e);
262-
throw ex;
258+
fc = asyncFilter.filter(fc);
259+
if (fc == null) {
260+
throw new NullPointerException("FilterContext is null");
263261
}
264262
}
265263

api/src/main/java/org/asynchttpclient/ListenableFuture.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@
3030
*/
3131
package org.asynchttpclient;
3232

33+
import java.util.concurrent.ExecutionException;
3334
import java.util.concurrent.Executor;
3435
import java.util.concurrent.Future;
36+
import java.util.concurrent.TimeUnit;
37+
import java.util.concurrent.TimeoutException;
3538

3639
/**
3740
* Extended {@link Future}
@@ -79,4 +82,60 @@ public interface ListenableFuture<V> extends Future<V> {
7982
* immediately but the executor rejected it.
8083
*/
8184
ListenableFuture<V> addListener(Runnable listener, Executor exec);
85+
86+
public class CompletedFailure<T> implements ListenableFuture<T>{
87+
88+
private final ExecutionException e;
89+
90+
public CompletedFailure(Throwable t) {
91+
e = new ExecutionException(t);
92+
}
93+
94+
public CompletedFailure(String message, Throwable t) {
95+
e = new ExecutionException(message, t);
96+
}
97+
98+
@Override
99+
public boolean cancel(boolean mayInterruptIfRunning) {
100+
return true;
101+
}
102+
103+
@Override
104+
public boolean isCancelled() {
105+
return false;
106+
}
107+
108+
@Override
109+
public boolean isDone() {
110+
return true;
111+
}
112+
113+
@Override
114+
public T get() throws InterruptedException, ExecutionException {
115+
throw e;
116+
}
117+
118+
@Override
119+
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
120+
throw e;
121+
}
122+
123+
@Override
124+
public void done() {
125+
}
126+
127+
@Override
128+
public void abort(Throwable t) {
129+
}
130+
131+
@Override
132+
public void touch() {
133+
}
134+
135+
@Override
136+
public ListenableFuture<T> addListener(Runnable listener, Executor exec) {
137+
exec.execute(listener);
138+
return this;
139+
}
140+
}
82141
}

api/src/test/java/org/asynchttpclient/async/FilterTest.java

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,19 @@
1212
*/
1313
package org.asynchttpclient.async;
1414

15-
import static org.testng.Assert.assertEquals;
16-
import static org.testng.Assert.assertNotNull;
17-
import static org.testng.Assert.fail;
15+
import static org.testng.Assert.*;
16+
17+
import java.io.IOException;
18+
import java.util.ArrayList;
19+
import java.util.Enumeration;
20+
import java.util.List;
21+
import java.util.concurrent.ExecutionException;
22+
import java.util.concurrent.Future;
23+
import java.util.concurrent.atomic.AtomicBoolean;
24+
25+
import javax.servlet.ServletException;
26+
import javax.servlet.http.HttpServletRequest;
27+
import javax.servlet.http.HttpServletResponse;
1828

1929
import org.asynchttpclient.AsyncHttpClient;
2030
import org.asynchttpclient.AsyncHttpClientConfig;
@@ -28,17 +38,6 @@
2838
import org.eclipse.jetty.server.handler.AbstractHandler;
2939
import org.testng.annotations.Test;
3040

31-
import javax.servlet.ServletException;
32-
import javax.servlet.http.HttpServletRequest;
33-
import javax.servlet.http.HttpServletResponse;
34-
35-
import java.io.IOException;
36-
import java.util.ArrayList;
37-
import java.util.Enumeration;
38-
import java.util.List;
39-
import java.util.concurrent.Future;
40-
import java.util.concurrent.atomic.AtomicBoolean;
41-
4241
public abstract class FilterTest extends AbstractBasicTest {
4342

4443
private static class BasicHandler extends AbstractHandler {
@@ -111,11 +110,10 @@ public void maxConnectionsText() throws Exception {
111110
AsyncHttpClient c = getAsyncHttpClient(b.build());
112111

113112
try {
114-
/* Response response = */c.preparePost(getTargetUrl()).execute().get();
113+
c.preparePost(getTargetUrl()).execute().get();
115114
fail("Should have timed out");
116-
} catch (IOException ex) {
117-
assertNotNull(ex);
118-
assertEquals(ex.getCause().getClass(), FilterException.class);
115+
} catch (ExecutionException ex) {
116+
assertTrue(ex.getCause() instanceof FilterException);
119117
} finally {
120118
c.close();
121119
}
@@ -126,7 +124,7 @@ public void basicResponseFilterTest() throws Exception {
126124
AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder();
127125
b.addResponseFilter(new ResponseFilter() {
128126

129-
// @Override
127+
@Override
130128
public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException {
131129
return ctx;
132130
}
@@ -139,8 +137,6 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
139137

140138
assertNotNull(response);
141139
assertEquals(response.getStatusCode(), 200);
142-
} catch (IOException ex) {
143-
fail("Should have timed out");
144140
} finally {
145141
c.close();
146142
}
@@ -171,8 +167,6 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
171167
assertNotNull(response);
172168
assertEquals(response.getStatusCode(), 200);
173169
assertEquals(response.getHeader("X-Replay"), "true");
174-
} catch (IOException ex) {
175-
fail("Should have timed out");
176170
} finally {
177171
c.close();
178172
}
@@ -203,8 +197,6 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
203197
assertNotNull(response);
204198
assertEquals(response.getStatusCode(), 200);
205199
assertEquals(response.getHeader("X-Replay"), "true");
206-
} catch (IOException ex) {
207-
fail("Should have timed out");
208200
} finally {
209201
c.close();
210202
}
@@ -236,8 +228,6 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
236228
assertNotNull(response);
237229
assertEquals(response.getStatusCode(), 200);
238230
assertEquals(response.getHeader("Ping"), "Pong");
239-
} catch (IOException ex) {
240-
fail("Should have timed out");
241231
} finally {
242232
c.close();
243233
}

0 commit comments

Comments
 (0)