Spring Retryable аннотация ClassNotFoundException

Я хотел бы использовать аннотацию @Retryable для restTemplate. Я добавил:

<dependency>
       <groupId>org.springframework.retry</groupId>
       <artifactId>spring-retry</artifactId>
       <version>1.2.1.RELEASE</version>
</dependency>

а также @EnableRetry для класса конфигурации. Я отметил метод:

restTemplate.exchange(url, HttpMethod.POST, request, String.class);

с (в новой теме)

@Retryable(maxAttempts=4,value=Exception.class,backoff=@Backoff(delay = 2000))

Но я получаю сообщение об ошибке от Каталины:

27-Oct-2017 18:11:41.023 SEVERE [http-nio-8080-exec-1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Around
    at 
<ommitted>
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Around
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1103)
    ... 61 more
Caused by: java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Around
    at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.<clinit>(ReflectiveAspectJAdvisorFactory.java:76)
    at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.<init>(AnnotationAwareAspectJAutoProxyCreator.java:53)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
    ... 63 more
Caused by: java.lang.ClassNotFoundException: org.aspectj.lang.annotation.Around
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    ... 70 more

27-Oct-2017 18:11:41.038 INFO [http-nio-8080-exec-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext

Что я делаю неправильно?

ОТРЕДАКТИРОВАНО: я продвинулся немного вперед. Обнаружил, что Spring Retry использует AOP, поэтому я добавил:

<dependency>
  <groupid>org.springframework</groupid>
  <artifactid>spring-aop</artifactid>
  <version>4.2.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.8</version>
</dependency>

Теперь я получаю другую ошибку:

27-Oct-2017 21:11:12.071 SEVERE [http-nio-8088-exec-5] org.springframework.web.servlet.DispatcherServlet.initServletBean Context initialization failed
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController' defined in file [(...)\HomeController.class]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.springframework.aop.framework.ObjenesisCglibAopProxy
    <ommitted>
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.aop.framework.ObjenesisCglibAopProxy
    at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:60)
    at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:105)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:468)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:349)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:298)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:421)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1558)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    ... 35 more

Чтобы изолировать проблему, я создал небольшой проект springMVC, и он такой же. Чтобы все было просто, использовалось всего несколько зависимостей. Это вывод из mvn dependency:tree:

[INFO] com.example:store:war:0.0.1-SNAPSHOT
[INFO] +- org.springframework:spring-webmvc:jar:4.0.3.RELEASE:compile
[INFO] |  +- org.springframework:spring-beans:jar:4.0.3.RELEASE:compile
[INFO] |  +- org.springframework:spring-context:jar:4.0.3.RELEASE:compile
[INFO] |  +- org.springframework:spring-core:jar:4.0.3.RELEASE:compile
[INFO] |  |  \- commons-logging:commons-logging:jar:1.1.3:compile
[INFO] |  +- org.springframework:spring-expression:jar:4.0.3.RELEASE:compile
[INFO] |  \- org.springframework:spring-web:jar:4.0.3.RELEASE:compile
[INFO] +- javax.servlet:jstl:jar:1.2:compile
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] +- org.springframework.retry:spring-retry:jar:1.2.1.RELEASE:compile
[INFO] +- com.mashape.unirest:unirest-java:jar:1.4.9:compile
[INFO] |  +- org.apache.httpcomponents:httpasyncclient:jar:4.1.1:compile
[INFO] |  |  +- org.apache.httpcomponents:httpcore:jar:4.4.4:compile
[INFO] |  |  \- org.apache.httpcomponents:httpcore-nio:jar:4.4.4:compile
[INFO] |  +- org.apache.httpcomponents:httpmime:jar:4.5.2:compile
[INFO] |  \- org.json:json:jar:20160212:compile
[INFO] +- org.springframework:spring-aop:jar:4.2.5.RELEASE:compile
[INFO] |  \- aopalliance:aopalliance:jar:1.0:compile
[INFO] \- org.aspectj:aspectjweaver:jar:1.8.8:compile

person user3529850    schedule 27.10.2017    source источник
comment
Вы добавили банку в Catalina?   -  person Xavier Bouclet    schedule 27.10.2017


Ответы (3)


У меня это сработало после добавления зависимости spring-boot-starter-aop, как показано ниже:

compile ("org.springframework.boot:spring-boot-starter-aop:1.5.10.RELEASE")
person Sahil Chhabra    schedule 01.03.2018

Я отвечу на свой вопрос, потому что сейчас это работает. Все необходимые зависимости:

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.2.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.3.11.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.10</version>
</dependency>

проверьте, нет ли повторяющихся зависимостей (например, по mvn dependency:tree, используйте <exclusions>, где необходимо). Убедитесь, что вы украсили свой класс конфигурации @EnableRetry. По какой-то причине вам нужно отделить вызывающую сторону от самого метода. Например:

@Retryable(maxAttempts = 4, value = {ResourceAccessException.class}, backoff = @Backoff(delay = 5000))
public ResponseEntity<String> tryToSendAndReturnResponseByRestTemplate(final RestTemplate restTemplate,
                                                                       final HttpEntity<MyObjDTO>
                                                                               request) {

    return restTemplate.exchange(resolveUrl(ENDPOINT_ADDRESS), HttpMethod.POST, request, String.class);
}

переходит в SenderManager класс, помеченный как f.e. @Service и в другом классе f.e. PhoneDirector класс, который вы называете:

senderManager.tryToSendAndReturnResponseByRestTemplate(restTemplate, request);

Он должен работать. (Если вам нужно указать, что должно быть возвращено, если после 4 (только здесь) попыток вы все еще получаете исключение, вы можете создать другой метод (в классе SenderManager), помеченный @Recover, например:

@Recover
public ResponseEntity<String> recoverWhenSendingMessageFailed(final ResourceAccessException e) {
    return new ResponseEntity<>(e.getMessage(), HttpStatus.REQUEST_TIMEOUT);
} 

Но если вам нужны аргументы из @Retryable (в методе @Recover), помните, что аргументы заполняются из списка аргументов неудачного метода. в том же порядке, что и неудачный метод, и с тем же типом возвращаемого значения

person user3529850    schedule 28.10.2017
comment
Было бы неплохо, если бы вы приняли ваш ответ. Кажется, что этот вопрос еще не имеет правильного ответа. - person Sahil Chhabra; 16.10.2018
comment
Это сработало, но я использовал только aspectjweaver без aop. - person aqteifan; 22.12.2020

spring-retry использует spring aop, убедитесь, что вы добавили aop в свой pom, и попробуйте выполнить чистую сборку приложения.

для весеннего приложения:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-aop</artifactId>
   <version>4.1.4.RELEASE</version>
</dependency>

для весенней загрузки:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.0.3.RELEASE</version>
</dependency>
person MrKulli    schedule 18.07.2018