3

I have a Spring service named EmailService like this:

@Service
public class EmailService {
    public void send (String recipient, String content) {
        // send out an email
    }
}

There are several other Spring services using EmailService, e.g. PaymentService uses EmailService to send emails to customers about their payments and RetailerReportService uses EmailService to send emails to retailers some selling reports.

I would like to know the amount of usage for EmailService and who are using it. Specifically, I want a bar chart that says "PaymentService called EmailService for 300 times a day" and "RetailerReportService called EmailService for 20 times a day".

Therefore, I want to add some code inside EmailService to monitor who are calling it. The first thing came to my mind is to retrieve the call stack with Thread.currentThread().getStackTrace(). However, since my application is using Spring framework, the call stack is full of proxy classes like org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint() or sun.reflect.NativeMethodAccessorImpl.invoke0(). Still, I can traverse the call stack and filter out unwanted classes by package names, but it would look ugly.

I would like to know if Spring provides a way to retrieve the caller Spring bean's name, so that I can use it inside EmailService to get names like paymentService or retailerReportService. Thank you.

johnlinp
  • 853
  • 6
  • 22
  • As Spring is all about separation of concerns and loose coupling, why not **consider** going the **AOP** way? Create an `@Aspect` class, create a method (`@Around, @Before or @After`) and then define a pointcut that points to the EmailService class' method or even better, consider creating a custom annotation class to handle your needs. This solution could also very easily scale and monitor other service classes that you might have. – Shashwat Kaundinya Oct 08 '21 at 18:01
  • @ShashwatKaundinya Thank you for the suggestion. Unfortunately, I couldn't find a way to retrieve the caller's name from the `ProceedingJoinPoint` in a @Aspect class. I can only find the callee's name. Could you please give me some hints about how to retrieve the caller's name in `ProceedingJoinPoint`? Thanks! – johnlinp Oct 08 '21 at 18:21
  • You could use `proceedingJoinPoint.getThis().getClass().getName()` to get the caller to your target. You could also match the method signature by leveraging Reflection now that you have a reference to your caller class. – Shashwat Kaundinya Oct 11 '21 at 05:33
  • I tried `proceedingJoinPoint.getThis().getClass().getName()`, but I got `com.sun.proxy.$Proxy200`. How do I get the "real" caller, e.g. `PaymentService` and `RetailerReportService`? – johnlinp Oct 11 '21 at 18:32

0 Answers0