Hystrix: (Javanica) HystrixCollapser failed while executing

Created on 20 Sep 2016  路  9Comments  路  Source: Netflix/Hystrix

Running the following code:

@HystrixCollapser(batchMethod = "getUsersTest")
public String getUserTest(String id) {
  return null;
}

@HystrixCommand
public List<String> getUsersTest(List<String> ids) {
  List<String> result = new ArrayList<>();
  for(String id : ids) {
      result.add("User " + id);
  }
  return result;
}

getUserTest("1");

HystrixCollapser throws the following error:

java.lang.RuntimeException: CommandCollapser HystrixCollapser failed while executing.

    at com.netflix.hystrix.HystrixCollapser.execute(HystrixCollapser.java:438)
    at com.netflix.hystrix.contrib.javanica.command.CommandExecutor.execute(CommandExecutor.java:52)
    at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect.methodsAnnotatedWithHystrixCommand(HystrixCommandAspect.java:90)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
...

If I change the implementation to return an Observable like in your documentation example:

@HystrixCollapser(batchMethod = "getUsersTest")
public Observable<String> getUserTest(String id) {
  return null;
}

@HystrixCommand
public List<String> getUsersTest(List<String> ids) {
  List<String> result = new ArrayList<>();
  for(String id : ids) {
      result.add("User " + id);
  }
  return result;
}

getUserTest("1");

HystrixCollapser throws the following exception:

java.lang.IllegalStateException: Return type of batch method must be java.util.List parametrized with corresponding type: expected (java.util.List<class rx.Observable>)getUsersTest(java.util.List<class java.lang.String>), but it's class java.lang.String

    at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect$CollapserMetaHolderFactory.create(HystrixCommandAspect.java:164)
    at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect$MetaHolderFactory.create(HystrixCommandAspect.java:106)
    at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect.methodsAnnotatedWithHystrixCommand(HystrixCommandAspect.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
...

Could you tell me what is wrong in my implementation? Thanks in advance!

javanica question

Most helpful comment

I've got a couple of other small changes I'd like to get in before the next release. Let me see if I can get to them tomorrow. If not, I'll cut a release with the current tip of master to unblock this.

All 9 comments

@dmgcodevil Could you take a look at this one? I'm familiar with debugging vanilla Hystrix collapsing, but not with the Javanica variants

I have already managed to make it works returning String and Future just adding this:

// Initialize Hystrix context
HystrixRequestContext context = HystrixRequestContext.initializeContext();

// HystrixCollapser calls here...

// Shutdown Hystrix context
context.shutdown();

But still it is not working with Observable. I am getting the same error that I showed before:

java.lang.IllegalStateException: Return type of batch method must be java.util.List parametrized with corresponding type: expected (java.util.List<class rx.Observable>)getUsersTest(java.util.List<class java.lang.String>), but it's class java.lang.String

    at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect$CollapserMetaHolderFactory.create(HystrixCommandAspect.java:164)
    at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect$MetaHolderFactory.create(HystrixCommandAspect.java:106)
    at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect.methodsAnnotatedWithHystrixCommand(HystrixCommandAspect.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
...

@dmgcodevil Why do you say that it should return Future if you already have a test working with Observable? https://github.com/Netflix/Hystrix/blob/master/hystrix-contrib/hystrix-javanica/src/test/java/com/netflix/hystrix/contrib/javanica/test/common/collapser/BasicCollapserTest.java#L86

@dmgcodevil Is the PR https://github.com/Netflix/Hystrix/pull/1320 related with my problem returning Observable?

If this is the case, when do you have plans to release a new version including these changes?

hi, collapser feature for observable was added relatively recently, so it might be not released yet. @mattrjacobs when are you going to make next release with this changes ?

I've got a couple of other small changes I'd like to get in before the next release. Let me see if I can get to them tomorrow. If not, I'll cut a release with the current tip of master to unblock this.

Sorry for the delay. I just released v1.5.6 from master, so it should have everything that's been submitted and approved. Please report back if this version fixes your issue

@mattrjacobs v1.5.6 fix the issue. Thank you very much! :smiley:

@HystrixCollapser(batchMethod = "findAll", scope = Scope.GLOBAL, collapserProperties = { @HystrixProperty(name="timerDelayInMilliseconds", value = "1000") }) public BaseDto find(Integer id) { System.out.println(id); return new BaseDto(id, null); }
you can use this 'scope = Scope.GLOBAL'锛寉ou can try it

Was this page helpful?
0 / 5 - 0 ratings