Reputation: 95
I'm working on a Spring Boot application with the following structure for sending messages
public interface MessageService {
void send(String message);
}
@Component("SendEmailService")
public class SendEmailService implements MessageService {
@Override
public void send(String message) {
System.out.println("SendEmailService");
}
}
@Component("SendSmsService")
public class SendSmsService implements MessageService {
@Override
public void send(String message) {
System.out.println("SendSms");
}
}
The application works well, but now I've got a new requirement. Some messages sent by email need a retry mechanism in case of failure. Here's how I implemented this:
public class ExceptionUtils {
public static void retryOnException(Runnable runnable, int maxRetries, long timeSeed) {
// Retry logic here
}
}
@Component("RetryableSendEmailService")
public class RetryableSendEmailService extends SendEmailService {
@Override
public void send(String message) {
ExceptionUtils.retryOnException(() -> super.send(message), 3, 5000);
}
}
Idea :
RetryableSendEmailService
that extends
SendEmailService
.RetryableSendEmailService
. If not, it can inject SendEmailService
.Concern: I'm worried that this might violate the Liskov Substitution Principle (LSP) from the SOLID principles. The principle states:
Objects of a superclass shall be replaceable with objects of its subclasses without breaking the application. This requires subclasses to behave in the same way as their superclasses.
Questions:
RetryableSendEmailService
violate
LSP since it changes the behavior of send by introducing retries?SOLID
principles, especially LSP
, while still achieving the desired
functionality?Upvotes: 0
Views: 75
Reputation: 22829
To be able to use retry the following criteria group should be met:
From the LSP persective the first two are important.
With retry it might happen that you send out the exact same message multiple times due to some transient issue.
In other words, your at most once semantic (the code without retry) is changed to at least once (with the retry).
As it was said in the previous point it might happen that the messaging provider sends out multiple copies of the same message. OR it has a dedicated de-duplication feature which helps to make the send
operation act idempotently. You should be aware of this before you apply retry "blindly".
Upvotes: 2