0

I ran into a problem that it is not possible to create a proxy for the bean. I use java, Spring. The code is below. I've been solving this issue for already several days and still have no idea what's wrong.

@SpringBootApplication
@EnableScheduling
@EnableCaching
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class ApiApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiApplication.class, args);
    }
}

I call my service method from another service:

@Transactional
public void updateState(List<Long> ids, ResourceState state) {
    ResourceService proxy = (ResourceService) AopContext.currentProxy();
    proxy.updateStateBySystem(Lists.newArrayList(repository.findAllById(ids)), state);
}

I invoke this method in the same service:

@Async
@Transactional
public void purchaseForOrder(Order order) {
    List<Resource> list = getResourcesForItem(order.getId(), null);
    updateState(list.stream().map(ApplicationModel::getId).collect(Collectors.toList()), ResourceState.PURCHASING);
}

And I get the following error message:

    Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.
    at org.springframework.aop.framework.AopContext.currentProxy(AopContext.java:69)
    at ru.sberbank.irpm.ApiApplication.main(ApiApplication.java:26)
    ... 5 more

Actually

  • Thank You for answer @Med. But I use an annotation-style config @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true). Aren't these things are the same? – SimonNechypurenko Dec 02 '21 at 13:44
  • Why should it return anything? There is nothing being invoked, and thus no current proxy is available. So your main code will never work as no invocation no proxy will be set. What is it that you are trying to achieve/ – M. Deinum Dec 02 '21 at 14:09
  • @M.Deinum that is an example. I use proxy in service class - ResourceService: ResourceService proxy = (ResourceService) AopContext.currentProxy(); I need this: ResourceService proxy = (ResourceService) AopContext.currentProxy(); proxy.updateStateBySystem(Lists.newArrayList(repository.findAllById(ids)), state); I need this to audit changes for my model using PostUpdateEventListener. If called directly, then the audit will not work updateStateBySystem(Lists.newArrayList(repository.findAllById(ids)) – SimonNechypurenko Dec 02 '21 at 14:26
  • That code is totally unreadable, please add it to your question. The current proxy will only be set **when** a method on a proxy is called. If that isn't the case (and your `main` doesn't) there is nu `currentProxy`. – M. Deinum Dec 02 '21 at 14:30
  • @M.Deinum I've added the information to the question – SimonNechypurenko Dec 02 '21 at 15:29
  • What is your usecase here? If you are trying to obtain the proxy for the service you are in to do a self invocation, just inject the service into itself (possible since Spring 4.3) instead of trying to hack around it (or just move the method to a different service). Also where is the `PostUpdateEventLIstener` in your question ther is no sign of that. – M. Deinum Dec 02 '21 at 15:59

1 Answers1

0

Many thanks to everyone for their interest in my task and willingness to help. I solved this problem by explicitly calling the service in the service itself.

ResourceService proxy =  ((ResourceService) applicationContext.getBean("resourceService")).getResourceServiceCurrentProxy();

And creating a method for calling the proxy in the service itself.

public ResourceService getResourceServiceCurrentProxy() {
     return (ResourceService) AopContext.currentProxy();
}
Krishna Majgaonkar
  • 1,532
  • 14
  • 25