Skip to content

Commit

Permalink
Improved TimeLimiterAspect message for not supported types (ReactiveX…
Browse files Browse the repository at this point in the history
  • Loading branch information
hexmind authored Feb 7, 2020
1 parent 7691102 commit 614f826
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.github.resilience4j.fallback;

import io.github.resilience4j.timelimiter.configure.IllegalReturnTypeException;
import io.vavr.CheckedFunction0;

/**
Expand All @@ -33,6 +34,8 @@ public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod,
return () -> {
try {
return supplier.apply();
} catch (IllegalReturnTypeException e) {
throw e;
} catch (Throwable throwable) {
return fallbackMethod.fallback(throwable);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.resilience4j.timelimiter.configure;

public class IllegalReturnTypeException extends IllegalArgumentException {

public IllegalReturnTypeException(Class<?> returnType, String methodName, String explanation) {
super(String.join(" ", returnType.getName(), methodName,
"has unsupported by @TimeLimiter return type.", explanation));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,11 @@
import io.github.resilience4j.reactor.timelimiter.TimeLimiterOperator;
import io.github.resilience4j.timelimiter.TimeLimiter;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class ReactorTimeLimiterAspectExt implements TimeLimiterAspectExt{

private static final Logger logger = LoggerFactory.getLogger(ReactorTimeLimiterAspectExt.class);

/**
* @param returnType the AOP method return type class
* @return boolean if the method has Reactor return type
Expand Down Expand Up @@ -58,10 +54,8 @@ public Object handle(ProceedingJoinPoint proceedingJoinPoint,
Mono<?> monoReturnValue = (Mono<?>) returnValue;
return monoReturnValue.compose(TimeLimiterOperator.of(timeLimiter));
} else {
logger.error("Unsupported type for Reactor timeLimiter {}", returnValue.getClass().getTypeName());
throw new IllegalArgumentException(
"Not Supported type for the timeLimiter in Reactor :" + returnValue.getClass().getName());

throw new IllegalReturnTypeException(returnValue.getClass(), methodName,
"Reactor expects Mono/Flux.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,13 @@
import io.github.resilience4j.timelimiter.transformer.TimeLimiterTransformer;
import io.reactivex.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;

import static io.github.resilience4j.utils.AspectUtil.newHashSet;

public class RxJava2TimeLimiterAspectExt implements TimeLimiterAspectExt {

private static final Logger logger = LoggerFactory.getLogger(RxJava2TimeLimiterAspectExt.class);
private final Set<Class<?>> rxSupportedTypes = newHashSet(ObservableSource.class,
SingleSource.class, CompletableSource.class, MaybeSource.class, Flowable.class);

Expand All @@ -54,11 +51,12 @@ public Object handle(ProceedingJoinPoint proceedingJoinPoint, TimeLimiter timeLi
throws Throwable {
TimeLimiterTransformer<?> timeLimiterTransformer = TimeLimiterTransformer.of(timeLimiter);
Object returnValue = proceedingJoinPoint.proceed();
return executeRxJava2Aspect(timeLimiterTransformer, returnValue);
return executeRxJava2Aspect(timeLimiterTransformer, returnValue, methodName);
}

@SuppressWarnings("unchecked")
private static Object executeRxJava2Aspect(TimeLimiterTransformer timeLimiterTransformer, Object returnValue) {
private static Object executeRxJava2Aspect(TimeLimiterTransformer timeLimiterTransformer,
Object returnValue, String methodName) {
if (returnValue instanceof ObservableSource) {
Observable<?> observable = (Observable<?>) returnValue;
return observable.compose(timeLimiterTransformer);
Expand All @@ -75,9 +73,8 @@ private static Object executeRxJava2Aspect(TimeLimiterTransformer timeLimiterTra
Flowable<?> flowable = (Flowable<?>) returnValue;
return flowable.compose(timeLimiterTransformer);
} else {
logger.error("Unsupported type for TimeLimiter RxJava2 {}", returnValue.getClass().getTypeName());
throw new IllegalArgumentException(
"Not Supported type for the TimeLimiter in RxJava2 :" + returnValue.getClass().getName());
throw new IllegalReturnTypeException(returnValue.getClass(), methodName,
"RxJava2 expects Flowable/Single/...");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ private Object proceed(ProceedingJoinPoint proceedingJoinPoint, String methodNam
}

if (!CompletionStage.class.isAssignableFrom(returnType)) {
throw new IllegalStateException("Not supported type by TimeLimiterAspect");
throw new IllegalReturnTypeException(returnType, methodName,
"CompletionStage expected.");
}

return handleJoinPointCompletableFuture(proceedingJoinPoint, timeLimiter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import reactor.core.publisher.Mono;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
Expand Down Expand Up @@ -40,11 +41,19 @@ public void testReactorTypes() throws Throwable {
assertThat(reactorTimeLimiterAspectExt.handle(proceedingJoinPoint, timeLimiter, "testMethod")).isNotNull();
}

@Test(expected = IllegalArgumentException.class)
@Test
public void shouldThrowIllegalArgumentExceptionWithNotReactorType() throws Throwable{
TimeLimiter timeLimiter = TimeLimiter.ofDefaults("test");
when(proceedingJoinPoint.proceed()).thenReturn("NOT REACTOR TYPE");
reactorTimeLimiterAspectExt.handle(proceedingJoinPoint, timeLimiter, "testMethod");

try {
reactorTimeLimiterAspectExt.handle(proceedingJoinPoint, timeLimiter, "testMethod");
fail("exception missed");
} catch (Throwable e) {
assertThat(e).isInstanceOf(IllegalReturnTypeException.class)
.hasMessage(
"java.lang.String testMethod has unsupported by @TimeLimiter return type. Reactor expects Mono/Flux.");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.mockito.junit.MockitoJUnitRunner;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
Expand Down Expand Up @@ -49,11 +50,19 @@ public void testRxJava2Types() throws Throwable {
assertThat(rxJava2TimeLimiterAspectExt.handle(proceedingJoinPoint, timeLimiter, "testMethod")).isNotNull();
}

@Test(expected = IllegalArgumentException.class)
@Test
public void shouldThrowIllegalArgumentExceptionWithNotRxJava2Type() throws Throwable{
TimeLimiter timeLimiter = TimeLimiter.ofDefaults("test");
when(proceedingJoinPoint.proceed()).thenReturn("NOT RXJAVA2 TYPE");
rxJava2TimeLimiterAspectExt.handle(proceedingJoinPoint, timeLimiter, "testMethod");

try {
rxJava2TimeLimiterAspectExt.handle(proceedingJoinPoint, timeLimiter, "testMethod");
fail("exception missed");
} catch (Throwable e) {
assertThat(e).isInstanceOf(IllegalReturnTypeException.class)
.hasMessage(
"java.lang.String testMethod has unsupported by @TimeLimiter return type. RxJava2 expects Flowable/Single/...");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public class TimeLimiterRecoveryTest {

@Test
public void testAsyncRecovery() throws Exception {
assertThat(testDummyService.async().toCompletableFuture().get(5, TimeUnit.SECONDS)).isEqualTo("recovered");
String result = testDummyService.async().toCompletableFuture().get(5, TimeUnit.SECONDS);
assertThat(result).isEqualTo("recovered");
}

@Test
Expand Down Expand Up @@ -60,9 +61,9 @@ public void testFlowableRecovery() {
assertThat(testDummyService.flowable().blockingFirst()).isEqualTo("recovered");
}

@Test
@Test(expected = IllegalReturnTypeException.class)
public void testSpelRecovery() {
assertThat(testDummyService.spelSync()).isEqualTo("recovered");
testDummyService.spelSync();
}

}

0 comments on commit 614f826

Please sign in to comment.