2
\$\begingroup\$

I have a Spring service that calls a few methods to

@Service
@RequiredArgsConstructor
@Slf4j
public class CarService {

    private final CarRepository carRepo;
    private final Mail mail;

    public void syncCars(Set<CarInfo> carInfos) {
        
        carInfos.forEach(carInfo -> 
               carRepo.findByCarInfo(carInfo.getId()) // returns Optional
                 .map(car -> updateCar(car, carInfo))
                 .orElseGet(() -> createCar(carInfo)));
    }

    public void createCar(Car car) {
       // some processing code
       // not shown for brevity
       mail.send("Following car created " + car);
    }

    public void updateCar(Car car, CarInfo carInfo) {           
       if (car.getPrice() - carInfo.getPrice() > 1000) {
         mail.send(String.format("Price for %s changed by %s", car, car.getPrice() - carInfo.getPrice());
       }
       // some processing code
       // not shown for brevity
    }

    public void deleteCar(Car car) {
       // some processing code
       // not shown for brevity
       mail.send("Following car deleted " + car);
    }
}

Mail is a Spring component:

@Component
@Slf4j
public class Mail {
    
    private final JavaMailSender javaMailSender;
    private final String appEmailAddress;
    private final String[] adminEmailAddresses;
    
    public Mail(JavaMailSender javaMailSender, MailProperties properties) {
        this.javaMailSender = javaMailSender;
        appEmailAddress = properties.getAppEmailAddress();
        adminEmailAddresses = properties.getAdminEmailAddresses();
    }
            
    public void sendEmail(String bodyText) {
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(appEmailAddress);
            message.setTo(adminEmailAddresses);
            message.setSubject("Car Sync Report");
            message.setText(bodyText);
            javaMailSender.send(message);
        } catch (MailException me) {
            log.error("Unable to send message due to the following error: "
                    + me.toString());
        }
    }
    
}

With this code, the CarService may send multiple emails on one call to syncCars. However, I would like for it to only send one email with all the messages.

I could create an instance field to hold the email body messages but CarService is a singleton and that would likely have concurrency issues. Another approach is to pass a String or StringBuilder to each method to collect the messages and then call mail.send at the end of the syncCars method. Is there another way to collect the messages to send in an email without passing an additional collection object to each method while avoiding concurrency issues? This seems like a cross-cutting concern here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.