-
Notifications
You must be signed in to change notification settings - Fork 95
CircuitBreaker Exception Mapper
Examples for how to take a CircuitBreakerException and automatically turn it into an exception meaningful to the application you may be writing.
Circuitbreakers include the ability to take the thrown CircuitBreakerException and turn it into another exception so that your application code need not know anything about CircuitBreakerException, but rather know about an exception of your choosing. Below is the detail about a simple mapping of CircuitBreakerException into a basic application exception.
The only “gotcha” is: The mapped exception must be either a `RuntimeException` (or child) or must be declared as thrown by the intercepted method. Otherwise, Java will throw an `UndeclaredThrowableException` at runtime.
Here’s what it took... Add the mapper declaration to the `CircuitBreakerBean` declaration:
<constructor-arg>
<bean class="net.applicaiton.device.service.AppCircuitBreakerExceptionMapper" />
</constructor-arg>
... as in:
<bean id="appCircuitBreaker" class="org.fishwife.jrugged.spring.CircuitBreakerBean">
<constructor-arg>
<bean class="net.applicaiton.device.service.AppCircuitBreakerExceptionMapper" />
</constructor-arg>
<property name="limit" value="3"/>
<property name="windowMillis" value="5000"/>
<property name="resetMillis" value="20000"/>
</bean>
public class AppCircuitBreakerExceptionMapper implements CircuitBreakerExceptionMapper<AppCircuitBreakerException> {
@Override
public AppCircuitBreakerException map(CircuitBreaker breaker, CircuitBreakerException exception) {
return new AppCircuitBreakerException(exception.getCause());
}
}
/*
* Use a runtime exception child to differentiate between the intercepted exception and the
* “thrown by circuitbreaker” exception (rather than mapping to what originally tripped the circuit).
* This is most useful when more than one external system is circuit-broken and you want to
* know which one threw. I’m not sure how to handle method-level granularity.
*/
public class AppCircuitBreakerException extends RuntimeException {
public AppCircuitBreakerException(Throwable cause) {
super(cause);
}
}
This example uses an existing, declared Exception (named `ThingException`) rather than a `RuntimeException`. In this case, the throws declaration of the method must match the parameterized mapper declaration.
This method:
public THing getThingFromId(String ID) throws ThingException {
...
}
Is mapped by:
<bean id="appCircuitBreaker" class="org.fishwife.jrugged.spring.CircuitBreakerBean">
<constructor-arg>
<bean class="net.comcast.cim.device.service.PlatformCircuitBreakerExceptionMapper" />
</constructor-arg>
<property name="limit" value="3"/>
<property name="windowMillis" value="5000"/>
<property name="resetMillis" value="20000"/>
</bean>
Using this Mapper:
public class AppBreakerExceptionMapper implements CircuitBreakerExceptionMapper<ThingException> {
@Override
public ThingException map(CircuitBreaker breaker, CircuitBreakerException exception) {
return new ThingException(AppError.TP_CIRCUIT_BREAKER_TRIPPED, exception);
}
}