Skip to content
Permalink
Browse files
Adding the ability to define exceptions via ThrowException which acce…
…pt a string as a parameter.
  • Loading branch information
mifosio-04-04-2018 committed Mar 28, 2017
1 parent 601a8d0 commit 8514adc3e8f28c7e19246576eadb21e8b32d50fc
Showing 2 changed files with 92 additions and 33 deletions.
@@ -62,26 +62,28 @@ public Exception decode(
}

private RuntimeException getAlternative(final String methodKey, final Response response) {
try {
final String bodyText = Util.toString(response.body().asReader());

if (response.status() == HttpStatus.BAD_REQUEST.value()) {
return new IllegalArgumentException(bodyText);
} else if (response.status() == HttpStatus.FORBIDDEN.value()) {
return new InvalidTokenException(bodyText);
} else if (response.status() == HttpStatus.NOT_FOUND.value()) {
return new NotFoundException(bodyText);
} else if (response.status() == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return new InternalServerError(bodyText);
} else {
return FeignException.errorStatus(methodKey, response);
}

} catch (IOException e) {

final String bodyText = stringifyBody(response);

if (response.status() == HttpStatus.BAD_REQUEST.value()) {
return new IllegalArgumentException(bodyText);
} else if (response.status() == HttpStatus.FORBIDDEN.value()) {
return new InvalidTokenException(bodyText);
} else if (response.status() == HttpStatus.NOT_FOUND.value()) {
return new NotFoundException(bodyText);
} else if (response.status() == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return new InternalServerError(bodyText);
} else {
return FeignException.errorStatus(methodKey, response);
}
}

private String stringifyBody(final Response response) {
try {
if (response.body() != null)
return Util.toString(response.body().asReader());
} catch (IOException ignored) {
}
return null;
}

private Optional<ThrowsException> getMatchingAnnotation(
@@ -123,16 +125,23 @@ private Optional<Exception> constructException(
final ThrowsException throwsExceptionAnnotations) {
try {
try {
final Constructor<? extends RuntimeException> oneArgumentConstructor =
final Constructor<? extends RuntimeException> oneResponseArgumentConstructor =
throwsExceptionAnnotations.exception().getConstructor(Response.class);

return Optional.of(oneArgumentConstructor.newInstance(response));
return Optional.of(oneResponseArgumentConstructor.newInstance(response));
} catch (final NoSuchMethodException e) {

final Constructor<? extends RuntimeException> noArgumentConstructor =
throwsExceptionAnnotations.exception().getConstructor();

return Optional.of(noArgumentConstructor.newInstance());
try {
final Constructor<? extends RuntimeException> noArgumentConstructor =
throwsExceptionAnnotations.exception().getConstructor();

return Optional.of(noArgumentConstructor.newInstance());
}
catch (final NoSuchMethodException e2) {
final Constructor<? extends RuntimeException> noStringArgumentConstructor =
throwsExceptionAnnotations.exception().getConstructor(String.class);

return Optional.of(noStringArgumentConstructor.newInstance(stringifyBody(response)));
}
}
} catch (final InvocationTargetException
| IllegalAccessException
@@ -26,6 +26,7 @@
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -48,37 +49,48 @@ public static Collection testCases() throws NoSuchMethodException {

final Response emptyInternalServerErrorResponse = Response.builder()
.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
.reason("blah")
.body("blah", Charset.defaultCharset())
.headers(Collections.emptyMap())
.build();

final Response emptyBadRequestResponse = Response.builder()
.status(HttpStatus.BAD_REQUEST.value())
.reason("blah")
.body("blah", Charset.defaultCharset())
.headers(Collections.emptyMap())
.build();

final Response emptyBadRequestResponseWithNoBody = Response.builder()
.status(HttpStatus.BAD_REQUEST.value())
.headers(Collections.emptyMap())
.build();

final Response emptyNotFoundRequestResponse = Response.builder()
.status(HttpStatus.NOT_FOUND.value())
.body("blah", Charset.defaultCharset())
.headers(Collections.emptyMap())
.build();

final Response emptyConflictResponse = Response.builder()
.status(HttpStatus.CONFLICT.value())
.reason("blah")
.body("blah", Charset.defaultCharset())
.headers(Collections.emptyMap())
.build();

final Response emptyIAmATeapotResponse = Response.builder()
.status(HttpStatus.I_AM_A_TEAPOT.value())
.reason("blah")
.body("blah", Charset.defaultCharset())
.headers(Collections.emptyMap())
.build();

final Response emptyUnauthorizedResponse = Response.builder()
.status(HttpStatus.UNAUTHORIZED.value())
.reason("blah")
.body("blah", Charset.defaultCharset())
.headers(Collections.emptyMap())
.build();

final Response emptyForbiddenResponse = Response.builder()
.status(HttpStatus.FORBIDDEN.value())
.reason("blah")
.body("blah", Charset.defaultCharset())
.headers(Collections.emptyMap())
.build();

@@ -91,7 +103,10 @@ public static Collection testCases() throws NoSuchMethodException {
Feign.configKey(OneMethodInterface.class, OneMethodInterface.class.getMethod("method"));

final String onceAnnotatedMethodKey =
Feign.configKey(OneMethodOneAnnotationInterface.class, OneMethodOneAnnotationInterface.class.getMethod("method"));
Feign.configKey(OneMethodOneAnnotationInterface.class, OneMethodOneAnnotationInterface.class.getMethod("method"));

final String onceAnnotatedWithStringExceptionMethodKey =
Feign.configKey(OneMethodOneAnnotationStringParameteredExceptionInterface.class, OneMethodOneAnnotationStringParameteredExceptionInterface.class.getMethod("method"));

ret.add(new TestCase("Methodless interface")
.clazz(MethodlessInterface.class)
@@ -135,12 +150,31 @@ public static Collection testCases() throws NoSuchMethodException {
.response(emptyBadRequestResponse)
.expectedResult(new ParameterlessException()));

ret.add(new TestCase("Interface with one method that has one annotation containing an exception which accepts a string parameter.")
.clazz(OneMethodOneAnnotationStringParameteredExceptionInterface.class)
.methodKey(onceAnnotatedWithStringExceptionMethodKey)
.response(emptyBadRequestResponse)
.expectedResult(new StringParameteredException("blah")));

ret.add(new TestCase("Bad request on an interface in which bad request isn't mapped.")
.clazz(AnnotationlessInterface.class)
.methodKey(annotationlessMethodKey)
.response(emptyBadRequestResponse)
.expectedResult(new IllegalArgumentException("blah")));

ret.add(new TestCase("Bad request with no body on an interface in which bad request isn't mapped.")
.clazz(AnnotationlessInterface.class)
.methodKey(annotationlessMethodKey)
.response(emptyBadRequestResponseWithNoBody)
.expectedResult(new IllegalArgumentException((String)null)));


ret.add(new TestCase("Not found request on an interface in which not found request isn't mapped.")
.clazz(AnnotationlessInterface.class)
.methodKey(annotationlessMethodKey)
.response(emptyNotFoundRequestResponse)
.expectedResult(new NotFoundException("blah")));

ret.add(new TestCase("Request with invalid token.")
.clazz(OneMethodOneAnnotationInterface.class)
.methodKey(onceAnnotatedMethodKey)
@@ -199,6 +233,14 @@ private interface OneMethodOneAnnotationInterface {
void method();
}


private interface OneMethodOneAnnotationStringParameteredExceptionInterface {

@SuppressWarnings("unused")
@ThrowsException(status = HttpStatus.BAD_REQUEST, exception = StringParameteredException.class)
void method();
}

private static class TestCase {

private final String name;
@@ -272,10 +314,18 @@ public ParameteredException(final Response response) {
}
}

private static class StringParameteredException extends RuntimeException {

@SuppressWarnings("WeakerAccess")
public StringParameteredException(final String response) {
super(response);
}
}

private static class WrongParameteredException extends RuntimeException {

public WrongParameteredException(final String message) {
super(message);
public WrongParameteredException(final Integer message) {
super(message.toString());
}
}
}

0 comments on commit 8514adc

Please sign in to comment.