I am thinking if we could implement a single fallback for all methods annotated with @HystrixCommand regardless of its method parameter arguments. Since for now every endpoint method must matched to its corresponding fallback method which is dependent on parameter arguments. It sounds so redundant and untidy code if we keep having same functionality for all those fallback methods. Another option is global or generic fallback added to @DefaultProperties attribute.
@RequestMapping(value = "/test1")
@HystrixCommand(fallbackMethod = "fallback")
public APIResponse test1(String param1) {
// some codes here
return APIResponse.success("success");
}
@RequestMapping(value = "/test2")
@HystrixCommand(fallbackMethod = "fallback")
public APIResponse test2() {
// some codes here
return APIResponse.success("success");
}
@RequestMapping(value = "/test3")
@HystrixCommand(fallbackMethod = "fallback")
public APIResponse test3(ObjectRequest obj) {
// some codes here
return APIResponse.success("success");
}
private APIResponse fallback() {
return APIResponse.failed("Server is busy");
}
This seems like a special-case which we haven't encountered of all methods returning the same type and wanting the same fallback. Anyone in the community also run into this case and feel like this feature is missing?
@mattrjacobs it was also needed by someone several months back Spring Hystrix Single Fallback with Method Arguments Not Matching .
We don't use the Javanica method of interacting with Hystrix internally, so this is not a feature we're looking to build. If you want to build it yourself, then can you coordinate with @dmgcodevil ?
This feature I think is really needed~ Can there be an common fallback method just simplely return null for all methods?
Hi folks, it's possible. There are two options:
@DefaultFallback
Object defaultFallback() {
return null;
}
@DefaultProperties : defaultFallback="defaultFallback"I think that the second option is better, wdyt ?
@dmgcodevil I'll go for second option. :)
Thanks in advance. :)
I'm thinking about defaultFallback return type: should it be Object, void or a concrete type? My understanding is that if defaultFallback can be applied for any command in the given class then a command return type should be compatible with defaultFallback one otherwise it will fail at runtime with "ClassCastException", e.g. :
@DefaultProperties(defaultFallback="fallback")
class Service {
@HystrixCommand
String foo(int i) {} // -> return type matches fallback one
Integer bar(int i) {} // -> fails at runtime with ClassCast
String fallback(){} // -> concrete return type
}
Using Object as fallback return type doesn't solve the problem either, it's even more error prone.
I think that this approach restricts an user in having commands with different return types and default fallback in the same class. Maybe it's ok, but sound brittle, isn't ?
As an alternative we can add defaultFallback in @HystrixCommand:
@HystrixCommand(defaultFallback="stringFallback")
String commandX(int a)
@HystrixCommand(defaultFallback="longFallback")
Long commandY(int a, int b)
@HystrixCommand(defaultFallback="longFallback")
Long commandZ(int a, int b, int c)
String stringFallback() {}
Long longFallback() {}
or to @DefaultProperties but defaultFallback return type should be void
@DefaultProperties
class Service {
@HystrixCommand
String commandX(int a)
@HystrixCommand
Long commandY(int a, int b)
void fallback() {}
}
Thoughts ?
In my thoughts if the developer uses the defaultFallback in @DefaultProperties he must know that all the return types of those annotated @HystrixCommand methods must be the same because he use it as a general fallback of that class, otherwise he needs to use the scope defaultFallback attribute of @HystrixCommand which must point to another fallback method. So if we restrict to only void return type I can say that it might be useless since most of the methods or function are returning any type of Object as a response dynamically.
So I imho the developer must know on how to use this kind of feature.
@angelom88 so your suggestion is to add defaultFallback to @DefaultProperties and @HystrixCommand, am I right ?
Yes correct, so developer is free which defaultFallback scope he will be using.
Many thanks. :)
Created PR
BTW: do you see an error in the following code ? :
@DefaultProperties(defaultFallback = "classDefaultFallback")
public static class Service {
static final String DEFAULT_RESPONSE = "class_def";
@HystrixCommand
public String get(String str) {
throw new RuntimeException();
}
// this fallback returns string
public String classDefaultFallback() {
return DEFAULT_RESPONSE;
}
@HystrixCommand(defaultFallback = "defaultFallback")
Long command(long l){
throw new RuntimeException();
}
@HystrixCommand
Long defaultFallback(){
return 0L;
}
}
@dmgcodevil what do you mean?
my bad, misspelled the question. there is an error in the above code:
@HystrixCommand
Long defaultFallback(){
return 0L;
}
it's command and fallback for Long command(long l) at the same time, when it's executed it fails because return type doesn't mach class scope default fallback, which is String. It should be changed to
@HystrixCommand(defaultFallback = "commandDefaultFallback")
Long command(long l){
throw new RuntimeException();
}
@HystrixCommand(fallbackMethod = "defaultFallback")
Long commandDefaultFallback(){ // defaultFallback -> commandDefaultFallback
return 0L;
}
Long defaultFallback() {
return 0L;
}
or, because this fallback never fails we can write;
@HystrixCommand(fallbackMethod="defaultFallback")
Long defaultFallback(){
return 0L;
}
just noticed that while was writing tests for this feature
How about if it will just support defaultFallback attribute only in class scope in @DefaultProperties? But the new feature API will prioritize the fallbackMethod if it is present in @HystrixCommand.
No, It's ok to have both actually. Especially as the twist with types caused by having default fallback defined in class scope. The example above just illustrates what happens if a command return type doesn't match and how it can be fixed.
I am currently trying to use default fallback method from https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica#default-fallback-for-class-or-concrete-command But the jar i am using from maven repository is 1.5.9 which doesn't have the defaultfallback method. Which jar should i use in order to get this defaultfallback feature in my Hystrix Properties.
I'll get a release cut tomorrow
@dmgcodevil any way if we can have a common default method for methods with different return types? We are currently have a lot of code repetition
Sample code -
public OwnerSideBurnResponse getOwnerSideBurnFallback(String id, String startDate, String endDate) {
return new OwnerSideBurnResponse();
}
public PaymentAuthVerifyResponse verifyChargesPreAuthFallback(String txnId) {
PaymentAuthVerifyResponse response = new PaymentAuthVerifyResponse();
return response;
}
public PaymentAuthVerifyResponse cancelPreAuthFallback(String txnId) {
PaymentAuthVerifyResponse response = new PaymentAuthVerifyResponse();
return response;
}
public PaymentAuthResponse chargePreAuthRequestFallback(PaymentAuthRequest chargeParams) {
PaymentAuthResponse response = new PaymentAuthResponse();
return response;
}
Also should we avoid returning empty object and return null? What do you suggest?
Hi guys, I want to know why the default fallback method cannot have parameters. In my view, same return type is okey, but maybe we can use Object[] as parameter for the default fallback method. Please let me know 馃檹
@dmgcodevil any way if we can have a common default method for methods with different return types? We are currently have a lot of code repetition
Sample code -public OwnerSideBurnResponse getOwnerSideBurnFallback(String id, String startDate, String endDate) {
return new OwnerSideBurnResponse();
}public PaymentAuthVerifyResponse verifyChargesPreAuthFallback(String txnId) { PaymentAuthVerifyResponse response = new PaymentAuthVerifyResponse(); return response; } public PaymentAuthVerifyResponse cancelPreAuthFallback(String txnId) { PaymentAuthVerifyResponse response = new PaymentAuthVerifyResponse(); return response; } public PaymentAuthResponse chargePreAuthRequestFallback(PaymentAuthRequest chargeParams) { PaymentAuthResponse response = new PaymentAuthResponse(); return response; }Also should we avoid returning empty object and return null? What do you suggest?
cc @sunbufu
I think I can change the code to accept any set of args in default fallback, i.e.:
Response getX(int i)
Response getY(int j, int k)
Response getZ(String s)
// possible default fallbacks
Response fallback (int i)
Response fallback (int i, int j)
Response fallback (int i, int j, int k)
Response fallback (int i, int j, int k)
Response fallback (int i, int j, String s)
````
however, it's fragile and tricky, you need to make sure you have a unique set of args across all command withing the same class.
another option is to pass command name and Object[] args, i.e.:
```java
Response fallback (String cmd, Object[] args) {
switch cmd {
case: "getX"
case: "getY"
case: "getZ"
}
Most helpful comment
Hi folks, it's possible. There are two options:
@DefaultProperties: defaultFallback="defaultFallback"I think that the second option is better, wdyt ?