简体   繁体   中英

Methods using @Retryable and @Recover don't call @Recover method with @SpringBootTest

I'm looking at some code in a SpringBoot application using @Retryable methods, with other methods marked @Recover. When we run the entire application and make remote calls that we know will fail, it does properly call the @Recover method.

However, when we run a test using @SpringBootTest with similar conditions, it never calls the @Recover method. We have lots of debug output. I did notice one situation in our running server (not the test case) where we saw something like the following:

Exception ExhaustedRetryException: Cannot locate recovery method;

I was looking for that in the debug output from the testcase, but I didn't find it.

The test class has the following annotations:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = { Application.class })

Our Application class has the following annotations:

@SpringBootApplication
@PropertySource("classpath:application.properties")
@ComponentScan(basePackages = "com")
@EnableAsync
@EnableRetry
@EnableCaching
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
        HazelcastAutoConfiguration.class, CacheAutoConfiguration.class, CassandraAutoConfiguration.class,
        CassandraDataAutoConfiguration.class, CassandraRepositoriesAutoConfiguration.class })

Is there some particular method in the Spring infrastructure that I can step through to see why it's not finding, or perhaps not even looking for, the recover method?

Update :

So I realized that when I execute the test in debug, I don't see the Spring RetryTemplate anywhere in the stacktrace. Isn't that what controls the flow from the Retryable method to the Recover method? That seems to point to some setup I'm missing in the test class, or perhaps an indication that this simply can't be done in a test class (I hope that's not true).

Update :

Ok, I managed to figure this out. This was happening because I had neglected to inject the bean from Spring, I just created one manually. That meant it wasn't wired to use the RetryTemplate, so it never attempted to find a @Recover method at all. Once I added "@Autowired" to the instance variable in the test class, it got past this problem (and hit me with the next problem, but I understand that one).

That exception is coming from the RecoverAnnotationRecoveryHandler so it looks like retry is operational but, for some reason it can't find the recovery method.

Method method = findClosestMatch(cause.getClass());
if (method == null) {
    throw new ExhaustedRetryException("Cannot locate recovery method", cause);
}

So, it's looking for a method that matches the exception.

findClosestMatch is simply scanning the discovered methods for a method with a parameter that matches.

I suggest you use a debugger and put a breakpoint in there to figure out why it can't find a match.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM