Skip to content

Commit 816cf50

Browse files
committed
Merge pull request OpenFeign#387 from padilo/completable_support
Added rx.Completable support
2 parents 755e2d4 + adb8c4b commit 816cf50

5 files changed

Lines changed: 103 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### Version 8.17
2+
* Adds support to RxJava Completable via `HystrixFeign` builder with fallback support
3+
* Upgraded hystrix-core to 1.4.26
4+
15
### Version 8.16
26
* Adds `@HeaderMap` annotation to support dynamic header fields and values
37
* Add support for default and static methods on interfaces

hystrix/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ sourceCompatibility = 1.6
44

55
dependencies {
66
compile project(':feign-core')
7-
compile 'com.netflix.hystrix:hystrix-core:1.4.21'
7+
compile 'com.netflix.hystrix:hystrix-core:1.4.26'
88
testCompile 'junit:junit:4.12'
99
testCompile 'org.assertj:assertj-core:1.7.1' // last version supporting JDK 7
1010
testCompile 'com.squareup.okhttp:mockwebserver:2.7.5'

hystrix/src/main/java/feign/hystrix/HystrixDelegatingContract.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.lang.reflect.ParameterizedType;
99
import java.lang.reflect.Type;
1010
import java.util.List;
11+
import rx.Completable;
1112
import rx.Observable;
1213
import rx.Single;
1314

@@ -46,6 +47,9 @@ public List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType) {
4647
&& ((ParameterizedType) type).getRawType().equals(Single.class)) {
4748
Type actualType = resolveLastTypeParameter(type, Single.class);
4849
metadata.returnType(actualType);
50+
} else if (type instanceof ParameterizedType
51+
&& ((ParameterizedType) type).getRawType().equals(Completable.class)) {
52+
metadata.returnType(void.class);
4953
}
5054
}
5155

hystrix/src/main/java/feign/hystrix/HystrixInvocationHandler.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.lang.reflect.Proxy;
3030
import java.util.LinkedHashMap;
3131
import java.util.Map;
32+
import rx.Completable;
3233
import rx.Observable;
3334
import rx.Single;
3435

@@ -117,6 +118,9 @@ protected Object getFallback() {
117118
} else if (isReturnsSingle(method)) {
118119
// Create a cold Observable as a Single
119120
return ((Single) result).toObservable().toBlocking().first();
121+
} else if (isReturnsCompletable(method)) {
122+
((Completable) result).await();
123+
return null;
120124
} else {
121125
return result;
122126
}
@@ -138,10 +142,16 @@ protected Object getFallback() {
138142
} else if (isReturnsSingle(method)) {
139143
// Create a cold Observable as a Single
140144
return hystrixCommand.toObservable().toSingle();
145+
} else if (isReturnsCompletable(method)) {
146+
return hystrixCommand.toObservable().toCompletable();
141147
}
142148
return hystrixCommand.execute();
143149
}
144150

151+
private boolean isReturnsCompletable(Method method) {
152+
return Completable.class.isAssignableFrom(method.getReturnType());
153+
}
154+
145155
private boolean isReturnsHystrixCommand(Method method) {
146156
return HystrixCommand.class.isAssignableFrom(method.getReturnType());
147157
}

hystrix/src/test/java/feign/hystrix/HystrixBuilderTest.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.junit.Rule;
2424
import org.junit.Test;
2525
import org.junit.rules.ExpectedException;
26+
import rx.Completable;
2627
import rx.Observable;
2728
import rx.Single;
2829
import rx.observers.TestSubscriber;
@@ -383,6 +384,81 @@ public void rxSingleListFallback() {
383384
assertThat(testSubscriber.getOnNextEvents().get(0)).containsExactly("fallback");
384385
}
385386

387+
@Test
388+
public void rxCompletableEmptyBody() {
389+
server.enqueue(new MockResponse());
390+
391+
TestInterface api = target();
392+
393+
Completable completable = api.completable();
394+
395+
assertThat(completable).isNotNull();
396+
assertThat(server.getRequestCount()).isEqualTo(0);
397+
398+
TestSubscriber<String> testSubscriber = new TestSubscriber<String>();
399+
completable.subscribe(testSubscriber);
400+
testSubscriber.awaitTerminalEvent();
401+
402+
testSubscriber.assertCompleted();
403+
testSubscriber.assertNoErrors();
404+
}
405+
406+
@Test
407+
public void rxCompletableWithBody() {
408+
server.enqueue(new MockResponse().setBody("foo"));
409+
410+
TestInterface api = target();
411+
412+
Completable completable = api.completable();
413+
414+
assertThat(completable).isNotNull();
415+
assertThat(server.getRequestCount()).isEqualTo(0);
416+
417+
TestSubscriber<String> testSubscriber = new TestSubscriber<String>();
418+
completable.subscribe(testSubscriber);
419+
testSubscriber.awaitTerminalEvent();
420+
421+
testSubscriber.assertCompleted();
422+
testSubscriber.assertNoErrors();
423+
}
424+
425+
@Test
426+
public void rxCompletableFailWithoutFallback() {
427+
server.enqueue(new MockResponse().setResponseCode(500));
428+
429+
TestInterface api =
430+
HystrixFeign.builder().target(TestInterface.class, "http://localhost:" + server.getPort());
431+
432+
Completable completable = api.completable();
433+
434+
assertThat(completable).isNotNull();
435+
assertThat(server.getRequestCount()).isEqualTo(0);
436+
437+
TestSubscriber<String> testSubscriber = new TestSubscriber<String>();
438+
completable.subscribe(testSubscriber);
439+
testSubscriber.awaitTerminalEvent();
440+
441+
testSubscriber.assertError(HystrixRuntimeException.class);
442+
}
443+
444+
@Test
445+
public void rxCompletableFallback() {
446+
server.enqueue(new MockResponse().setResponseCode(500));
447+
448+
TestInterface api = target();
449+
450+
Completable completable = api.completable();
451+
452+
assertThat(completable).isNotNull();
453+
assertThat(server.getRequestCount()).isEqualTo(0);
454+
455+
TestSubscriber<String> testSubscriber = new TestSubscriber<String>();
456+
completable.subscribe(testSubscriber);
457+
testSubscriber.awaitTerminalEvent();
458+
459+
testSubscriber.assertCompleted();
460+
}
461+
386462
@Test
387463
public void plainString() {
388464
server.enqueue(new MockResponse().setBody("\"foo\""));
@@ -520,6 +596,9 @@ interface TestInterface {
520596
@RequestLine("GET /")
521597
@Headers("Accept: application/json")
522598
List<String> getList();
599+
600+
@RequestLine("GET /")
601+
Completable completable();
523602
}
524603

525604
class FallbackTestInterface implements TestInterface {
@@ -600,5 +679,10 @@ public List<String> getList() {
600679
fallbackResult.add("fallback");
601680
return fallbackResult;
602681
}
682+
683+
@Override
684+
public Completable completable() {
685+
return Completable.complete();
686+
}
603687
}
604688
}

0 commit comments

Comments
 (0)