How can I separate business logic and email sending functionality?

让人想犯罪 __ 提交于 2019-12-22 12:44:48

问题


I have a requirement in my java web application where I need to send email alerts for certain conditions. For this I have used javax mail api and sending email works just fine. But the problem is the programs executions waits until the methods for sending the email are executed. As there are hundreds of email to be sent at various points ... this reduces the performance significantly.

I am using spring and have also used spring aop. Can anyone suggest me how can I separate my business logic and sending email functionality. It should be like -

Sending emails is my advice which gets executed when xyz method is called - So main execution should not wait for advice to finish its execution rather it should return back and execute further business logic thus email sending executed separately.

Here creating new threads seems obvious choice. But I think there could be some better way, is there? Thanks.


回答1:


What you describe is asynchronous execution and natural way to do async execution is Java is to use threads.

You can introduce some Executor, e.g., Executors.newFixedThreadPool(), and use it to offload mailing task into separate threads.

Aspect itself is a unsuitable place for this, since this would introduce state into aspect, for example, you may want to check if mail task was successful by using returned Future:

class Mailer {
    private final ExecutorService executor = Executors.newFixedThreadPool(maxMailingThreads);
    //...
        public void doMail(MailTask anEmail) {
            Future<MailTaskResult> future = executor.submit(new MailTask(anEmail));
            future.get().isSuccessful(); // handle success or failure somehow
        }

Better move this logic into separate class and call it from aspect somehow.




回答2:


You can make the mail sending method @Async. This way Spring will execute this in a seperate thread. Read this blog post about it: Creating Asynchronous Methods




回答3:


Treat the email sending functionality like an IO device. Make it a plugin to your business logic. Do not allow any knowledge of the fact that you're even talking to the email code into your business logic. Make the email logic depend on the business logic. Never the other way around.

Here's a very good talk about this kind of architecture:

https://vimeo.com/97530863

Here's a series debating it:

https://www.youtube.com/watch?v=z9quxZsLcfo

Here's a ruby master demonstrating it with real code. We miss him.

https://www.youtube.com/watch?v=tg5RFeSfBM4

If your business rules are interesting enough to be worth respecting than this is the way to make them the masters of your application. Express them only using java. Don't accept any help. No spring, no weird annotations, just business rules. Push all that "help" out to the mail code.

Do this and your app will scale well. I think this is the best way to put it:

That's from a hexagonal architecture post. But the idea of giving your business rules a safe place to live removed from implementation detail shows up in many architectures. This answer rounds them up nicely.




回答4:


Use a localhost MTA (like OpenSMTPD) and then relay to your real SMTP server, like Amazon SES ("Satellite" mode). It won't block.

I did a test, and sent 1000 emails in 2.8 seconds this way

It's simpler than doing async in java, and is useful across multiple applications.

As for separating logic, raise a Spring Application Event when needed, and make another class to listen to it, and send your email from there. Or consider something like Guava's EventBus




回答5:


Consider creating a separate thread to send emails within your application. This will allow parallel execution(application+email sending).

If you would want another approach you can create a separate back end application that only sends emails. Although you will need to submit the email messages to the application. An asynchronous way to do this is to send a JMS message to the email application.



来源:https://stackoverflow.com/questions/29286473/how-can-i-separate-business-logic-and-email-sending-functionality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!