If I use status 400 to handle "invalid input", with @HystrixCommand I'm able to specify set of exceptions (assuming custom error decoder) to be treated as "handled" and they won't break the circuit. With use of HystrixFeign.builder I have to remove @HystrixCommand and I do not see the way to specify my custom exceptions as well as how to specify that http 400 should not break circuit.
Comment From: tjuchniewicz
@vasilievip It would be great to have it integrated into @FeignClient.
Maybe it will help you: If you have custom ErrorDecoder you can apply it to @FeignClient and return HystrixBadRequestException from there and this will not break circuit.
Comment From: vasilievip
Maybe it will help you: If you have custom ErrorDecoder
Thanks! Will try it, but I would rather consider this as a workaround.
What I did already - disabled spring wired hystrix for my client and wrapped it into MyHystrixEnabledFeignClient with @HystrixCommand when I specify fallback and list of exceptions which are BadRequest ones.
Comment From: vasilievip
Thanks! Will try it, but I would rather consider this as a workaround.
BTW: As far as I remember - error decoder was executed after hystrix and not before
Comment From: tjuchniewicz
Could you share some code concept? How do you use @HystrixCommand with @FeignClient?
Comment From: tjuchniewicz
BTW: As far as I remember - error decoder was executed after hystrix and not before
Looks like before. I have working example for solution described above.
Comment From: vasilievip
I'll have to double check on it.
Here is some my code snippets:
@FeignClient(
value = "BackupServer/buckets",
configuration = {BackupServiceClientFeignContext.class}
)
public interface BackupServiceRestClient {
...
@Configuration
public class BackupServiceClientFeignContext {
@Bean
@Scope("prototype")
@Primary
//To disable hystrix
public Feign.Builder feignBuilder() {
return Feign.builder();
}
@Bean
public ErrorDecoder cbsErrorDecoder() {
return new BackupServiceClientFeignErrorDecoder();
}
}
public class DefaultBackupServiceClientHystrixDecorator implements BackupServiceClientHystrixDecorator {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final BackupServiceRestClient restClient;
public DefaultBackupServiceClientHystrixDecorator(BackupServiceRestClient restClient) {
this.restClient = restClient;
}
@HystrixCommand(
fallbackMethod = "getValueFallback",
ignoreExceptions = {NoRecordFoundException.class, BucketAbsentException.class},
commandProperties =
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
)
@Metered(argIdToIncludeToMetrics = 0)
public byte[] getValue(String bucket, String key) {
try {
return restClient.getRecord(stream, key);
} catch (BackupServiceException e) {
throw e;
} catch (Exception e) {
throw new ServiceUnavailableException(stream, key, e);
}
}
Comment From: vasilievip
fallbackMethod with throwable works for me from following version of javanica
<hystrix-javanica.version>1.4.25</hystrix-javanica.version>
Comment From: tjuchniewicz
Your solution with decorator is very interesting. Maybe I will use it ;-)
My current solution:
@FeignClient(
value = "BackupServer/buckets",
configuration = {BackupServiceClientFeignContext.class},
fallback = BackupServiceRestClientFallback.class
)
public interface BackupServiceRestClient extends BackupServiceRest {
}
@Configuration
public class BackupServiceClientFeignContext {
// Hystrix is enabled
@Bean
public ErrorDecoder cbsErrorDecoder() {
// Decoder reads declared exceptions from interface method
// and throws it when found in response wrapped in HystrixBadRequestException.
// Service response contains custom entity with exception name occurred on service side.
// or just converts 400-499 HTTP errors to HystrixBadRequestException
return new BackupServiceClientFeignErrorDecoder(BackupServiceRest.class);
}
}
@Component
public class DefaultBackupService {
@Autowired
private BackupServiceRestClient restClient;
public byte[] getValue(String bucket, String key) {
try {
return restClient.getRecord(stream, key);
} catch(HystrixBadRequestException e) {
Throwable cause = e.getCause();
if(cause instanceof NoRecordFoundException) {
// cast to NoRecordFoundException
}
}
}
}
Comment From: vasilievip
Looks like before. I have working example for solution described above.
Just tested and your approach with HystrixBadRequestException works fine as well, thanks!
Comment From: OlgaMaciaszek
Closing as Hystrix is no longer supported.