簡単な質問:トランザクションとリソースインジェクションがPOJOで機能するように、ステートレスEJBによって呼び出されたPOJOをEJBのコンテキストで動作させる方法はありますか?
具体的には、私がやろうとしていることのコンテキストで:POJOを呼び出してメッセージを送信する前に、データベース内の一部のデータを保持するEJBのトランザクションにPOJO JMSプロデューサーを含めるにはどうすればよいですか?例外が原因で送信された場合、データベーストランザクションもロールバックされますか?メールを非同期で送信したい。
これは幸せな道です(ステートレスセッション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内に移動し、正しく実行されたテストを行ったことに言及する必要があります...しかし、アプリの他の部分で使用するために、これを別のクラスで機能させる必要があります。