交易和发送电子邮件

时间:2010-12-02 03:30:22

标签: java spring email transactions

考虑用户在Web应用程序上创建新帐户的常见用例,以及应用程序向用户的地址发送确认电子邮件。从我所看到的,这通常以3种方式之一实现:

  1. Web控制器调用服务方法,该方法在单个事务中创建用户帐户并发送电子邮件。
  2. Web控制器调用一个服务方法(使用tx propagation = never),它调用自身的第一个方法在事务中创建用户帐户,然后调用第二个方法来发送电子邮件。
  3. Web控制器调用第一个服务方法,该方法在事务中创建用户帐户,然后调用第二个发送电子邮件的服务方法。
  4. 第一种方法简单明了,但存在发送电子邮件后回滚事务的风险,从而使电子邮件无效。第二种方法更复杂,但它保证只有在用户创建实际成功时才发送电子邮件。第三种方法很简单,但是将Web层与业务逻辑加重,这是不应该知道的。

    是否有一种更简单的方法,也许是AOP驱动的,可以保证只有在用户创建事务实际成功时才会发送电子邮件?我认为第一种方法可能会失败,我是否会偏执?

    我们正在使用Java EE + Spring堆栈,并且愿意集成其他API(AOP?Spring Integration?)来实现这一目标。

    干杯!

4 个答案:

答案 0 :(得分:6)

我目前用于解决此问题的另一个选项:

http://download.oracle.com/javaee/6/api/javax/transaction/Synchronization.html

答案 1 :(得分:5)

要发送电子邮件,建议使用队列并安排每隔5或15分钟发送一次电子邮件。 队列将存储在数据库中,因此在事务中。然后安排一个过程,定期从该队列发送电子邮件。

这是我发现确保电子邮件仅在交易完成和提交时发送的唯一方式,因为根据定义,电子邮件不依赖于任何类型的数据库事务。

答案 2 :(得分:0)

我会为电子邮件添加一个像ActiveMQ这样的轻量级JMS层,它很容易设置和集成(甚至嵌入)Spring。那你有

1)用户创建交易&发送在1个事务中发生的JMS消息。如果任何一个失败,你仍然处于良好状态(提交或同时回滚并向用户提出错误)

2)如果JMS使用者无法发送电子邮件,您可以设置JMS队列重试几次,您将有更好的解决方案来管理您的电子邮件系统的暂时性问题。

答案 3 :(得分:0)

使用Quartz或类似的东西对数据库表进行排队并运行调度程序是合理且易于实现的。

将RabbitMQ用于这些功能开发也是个好主意。 RabbitMQ非常容易配置,并且可以用于系统之间发布/订阅交互的大多数情况,即使您可能需要实现应用程序级别的ack和从RabbitMQ订阅消息并通过SMTP发送电子邮件的小型应用程序。

这可能听起来有些过分,但您可以将此#2解决方案用于将来需要电子邮件发送的每个系统。您仍然可以使用基于数据库队列的模型,但会使用昂贵的数据库CPU /资源来发送emmail。