简短的问题:有没有办法强制由无状态 EJB 调用的 POJO 存在于 EJB 的上下文中,以便事务和资源注入将在 POJO 中工作?
特别是在我想要做的事情的上下文中:如何在调用 POJO 发送消息之前将 POJO JMS Producer 包含在 EJB 的事务中,该事务在数据库中保留一些数据,这样如果消息不能由于异常被发送,数据库事务也会回滚吗?我想异步发送邮件。
这是幸福的道路(从无状态会话 bean 开始):
- 将数据保存到数据库 // 这有效
- 从持久化的数据中提取选择数据并将其放置在自定义的“消息”类中(实际上是一个 dto)
- 调用 EmailQueueMessenger POJO 的 sendEmail 方法,将消息对象传递给它。
- 消息被发送到 MDB 以处理和发送电子邮件(不是问题的一部分,只是为了完整性)
下面的代码有效,如果我在上下文查找中强制出错,它就不会回滚调用类中的数据库“持久”。顺便说一句,我也无法让@Resource 注入工作。
//In the EJB
EmailQueueMessenger eqm = new EmailQueueMessenger();
eqm.sendEmail(messageObject);
// mailObject will be translated into an email message at the other end of the queue.
/******************** POJO Below ************/
public class EmailQueueMessenger implements Serializable {
// Resource injection doesn't work... using 'lookup' below, which does work.
// @Resource(name = "jms/EmailerQueueConnectionFactory")
// private ConnectionFactory connectionFactory;
// @Resource(name = "jms/EmailerQueue")
// private Destination EmailerQueue;
public EmailQueueMessenger() {
}
public void sendEmail(MailMessageDTO theMessage) {
Context ctx = null;
try {
ctx = new InitialContext();
ConnectionFactory connectionFactory = (ConnectionFactory) ctx.lookup("jms/EmailerQueueConnectionFactory");
System.out.println("JMS Producer CTX Name In Namespace: " + ctx.getNameInNamespace());
//Destination EmailerQueue = (Destination) ctx.lookup("jms/ERROR"); // forces exception
Destination EmailerQueue = (Destination) ctx.lookup("jms/EmailerQueue"); // normal working code
try {
Connection con = connectionFactory.createConnection();
Session session = con.createSession(false,
Session.AUTO_ACKNOWLEDGE);
MessageProducer msgProd = session.createProducer(EmailerQueue);
...
我试过添加:
@TransactionAttribute(TransactionAttributeType.MANDATORY)
@Stateless
到 POJO 定义,但它没有任何区别。
FWIW 我为 EmailQueueMessenger 使用了一个单独的类,因为应用程序的其他部分需要偶尔发送电子邮件,所以不想重复代码。
应该提到我做了一个测试,我将所有 JMS 东西移动到第一个 EJB 中并且它运行正确......但我需要它在一个单独的类中工作以供应用程序的其他部分使用。