| 37486 |
amit |
1 |
package com.spice.profitmandi.service.mail;
|
|
|
2 |
|
|
|
3 |
import com.spice.profitmandi.common.mail.MailQueue;
|
|
|
4 |
import com.spice.profitmandi.common.mail.MailRequest;
|
|
|
5 |
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
6 |
import org.springframework.stereotype.Service;
|
|
|
7 |
|
|
|
8 |
/**
|
|
|
9 |
* Publishes {@link MailOutboxService} as a {@link MailQueue} without letting
|
|
|
10 |
* MailOutboxService implement the interface itself.
|
|
|
11 |
*
|
|
|
12 |
* That indirection is load-bearing. MailOutboxService has @Transactional methods,
|
|
|
13 |
* so Spring must proxy it, and @EnableTransactionManagement here runs with the
|
|
|
14 |
* default proxyTargetClass=false. While the class implements no interface Spring
|
|
|
15 |
* proxies it with a CGLIB subclass, which is still a MailOutboxService. The moment
|
|
|
16 |
* it implements one, Spring switches to a JDK proxy that implements only that
|
|
|
17 |
* interface -- and the 39 sites which inject the concrete MailOutboxService all
|
|
|
18 |
* fail with BeanNotOfRequiredTypeException, taking the whole context down with
|
|
|
19 |
* them. That is exactly what happened in production on 2026-08-31.
|
|
|
20 |
*
|
|
|
21 |
* So the interface lives here instead: this adapter carries no transactional
|
|
|
22 |
* annotations, and its consumers (MailQueueHolder, EmailServiceImpl) inject it by
|
|
|
23 |
* the MailQueue interface, which a proxy of either kind satisfies.
|
|
|
24 |
*/
|
|
|
25 |
@Service
|
|
|
26 |
public class MailQueueAdapter implements MailQueue {
|
|
|
27 |
|
|
|
28 |
private final MailOutboxService mailOutboxService;
|
|
|
29 |
|
|
|
30 |
@Autowired
|
|
|
31 |
public MailQueueAdapter(MailOutboxService mailOutboxService) {
|
|
|
32 |
this.mailOutboxService = mailOutboxService;
|
|
|
33 |
}
|
|
|
34 |
|
|
|
35 |
@Override
|
|
|
36 |
public void queue(MailRequest request) {
|
|
|
37 |
mailOutboxService.queue(request);
|
|
|
38 |
}
|
|
|
39 |
}
|