Skip to content

Commit dd5a316

Browse files
authored
Merge pull request #21 from SimY4/master
Fixes the case where response decoders were unable to parse the type.
2 parents fc4b6b8 + f61b383 commit dd5a316

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

src/main/java/feign/error/ExceptionGenerator.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515

1616
import feign.Request;
1717
import feign.Response;
18+
import feign.Types;
1819
import feign.codec.DecodeException;
1920
import feign.codec.Decoder;
2021
import java.io.IOException;
2122
import java.lang.annotation.Annotation;
2223
import java.lang.reflect.Constructor;
2324
import java.lang.reflect.InvocationTargetException;
25+
import java.lang.reflect.Type;
2426
import java.util.Arrays;
2527
import java.util.Collection;
2628
import java.util.HashMap;
@@ -46,11 +48,11 @@ class ExceptionGenerator {
4648
private final Integer bodyIndex;
4749
private final Integer headerMapIndex;
4850
private final Integer numOfParams;
49-
private final Class bodyType;
51+
private final Type bodyType;
5052
private final Class<? extends Exception> exceptionType;
5153
private final Decoder bodyDecoder;
5254

53-
ExceptionGenerator(Integer bodyIndex, Integer headerMapIndex, Integer numOfParams, Class bodyType,
55+
ExceptionGenerator(Integer bodyIndex, Integer headerMapIndex, Integer numOfParams, Type bodyType,
5456
Class<? extends Exception> exceptionType, Decoder bodyDecoder) {
5557
this.bodyIndex = bodyIndex;
5658
this.headerMapIndex = headerMapIndex;
@@ -67,7 +69,7 @@ Exception createException(Response response) throws InvocationTargetException,
6769
Class<?>[] paramClasses = new Class[numOfParams];
6870
Object[] paramValues = new Object[numOfParams];
6971
if (bodyIndex >= 0) {
70-
paramClasses[bodyIndex] = bodyType;
72+
paramClasses[bodyIndex] = Types.getRawType(bodyType);
7173
paramValues[bodyIndex] = resolveBody(response);
7274
}
7375
if (headerMapIndex >= 0) {
@@ -84,7 +86,7 @@ Class<? extends Exception> getExceptionType() {
8486
}
8587

8688
private Object resolveBody(Response response) {
87-
if (bodyType.getClass().equals(Response.class)) {
89+
if (bodyType instanceof Class<?> && ((Class<?>) bodyType).isInstance(response)) {
8890
return response;
8991
}
9092
try {
@@ -114,13 +116,13 @@ public Builder withResponseBodyDecoder(Decoder bodyDecoder) {
114116

115117
public ExceptionGenerator build() {
116118
Constructor<? extends Exception> constructor = getConstructor(exceptionType);
117-
Class<?>[] parameterTypes = constructor.getParameterTypes();
119+
Type[] parameterTypes = constructor.getGenericParameterTypes();
118120
Annotation[][] parametersAnnotations = constructor.getParameterAnnotations();
119121

120122
Integer bodyIndex = -1;
121123
Integer headerMapIndex = -1;
122124
Integer numOfParams = parameterTypes.length;
123-
Class bodyType = null;
125+
Type bodyType = null;
124126

125127
for (int i = 0; i < parameterTypes.length; i++) {
126128
Annotation[] paramAnnotations = parametersAnnotations[i];
@@ -129,7 +131,7 @@ public ExceptionGenerator build() {
129131
if (annotation.annotationType().equals(ResponseHeaders.class)) {
130132
checkState(headerMapIndex == -1,
131133
"Cannot have two parameters tagged with @ResponseHeaders");
132-
checkState(parameterTypes[i].equals(Map.class),
134+
checkState(Types.getRawType(parameterTypes[i]).equals(Map.class),
133135
"Response Header map must be of type Map, but was %s", parameterTypes[i]);
134136
headerMapIndex = i;
135137
foundAnnotation = true;

src/test/java/feign/error/AnnotationErrorDecoderExceptionConstructorsTest.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*/
1414
package feign.error;
1515

16+
import feign.codec.Decoder;
17+
import feign.optionals.OptionalDecoder;
1618
import org.junit.Test;
1719
import org.junit.runner.RunWith;
1820
import org.junit.runners.Parameterized;
@@ -22,6 +24,7 @@
2224
import java.util.Collection;
2325
import java.util.HashMap;
2426
import java.util.Map;
27+
import java.util.Optional;
2528
import static org.assertj.core.api.Assertions.assertThat;
2629
import static feign.error.AnnotationErrorDecoderExceptionConstructorsTest.TestClientInterfaceWithDifferentExceptionConstructors;
2730
import static feign.error.AnnotationErrorDecoderExceptionConstructorsTest.TestClientInterfaceWithDifferentExceptionConstructors.*;
@@ -69,6 +72,9 @@ public static Iterable<Object[]> data() {
6972
NON_NULL_HEADERS},
7073
{"test Declared Constructor", 509,
7174
DefinedConstructorWithAnnotationForNonSupportedBody.class, NULL_BODY, NO_HEADERS},
75+
{"test Declared Constructor", 510,
76+
DefinedConstructorWithAnnotationForOptionalBody.class, Optional.of(NON_NULL_BODY),
77+
NO_HEADERS},
7278
});
7379
}
7480

@@ -91,7 +97,9 @@ public static Iterable<Object[]> data() {
9197
public void test() throws Exception {
9298

9399
AnnotationErrorDecoder decoder = AnnotationErrorDecoder
94-
.builderFor(TestClientInterfaceWithDifferentExceptionConstructors.class).build();
100+
.builderFor(TestClientInterfaceWithDifferentExceptionConstructors.class)
101+
.withResponseBodyDecoder(new OptionalDecoder(new Decoder.Default()))
102+
.build();
95103

96104
Exception genericException = decoder.decode(feignConfigKey("method1Test"),
97105
testResponse(errorCode, NON_NULL_BODY, NON_NULL_HEADERS));
@@ -122,8 +130,9 @@ interface TestClientInterfaceWithDifferentExceptionConstructors {
122130
@ErrorCodes(codes = {508},
123131
generate = DefinedConstructorWithAnnotationForHeadersButNotForBody.class),
124132
@ErrorCodes(codes = {509},
125-
generate = DefinedConstructorWithAnnotationForNonSupportedBody.class)
126-
133+
generate = DefinedConstructorWithAnnotationForNonSupportedBody.class),
134+
@ErrorCodes(codes = {510},
135+
generate = DefinedConstructorWithAnnotationForOptionalBody.class)
127136
})
128137
void method1Test();
129138

@@ -201,6 +210,24 @@ public Object body() {
201210
}
202211
}
203212

213+
class DefinedConstructorWithAnnotationForOptionalBody extends ParametersException {
214+
Optional<String> body;
215+
216+
public DefinedConstructorWithAnnotationForOptionalBody() {
217+
throw new UnsupportedOperationException("Should not be called");
218+
}
219+
220+
@FeignExceptionConstructor
221+
public DefinedConstructorWithAnnotationForOptionalBody(@ResponseBody Optional<String> body) {
222+
this.body = body;
223+
}
224+
225+
@Override
226+
public Object body() {
227+
return body;
228+
}
229+
}
230+
204231
class DefinedConstructorWithAnnotationForNonSupportedBody extends ParametersException {
205232
TestPojo body;
206233

0 commit comments

Comments
 (0)