The short question: Is there a way to force a POJO called by a stateless EJB to live in the context of the EJB so that transactions and resource injection will work in the POJO?
Specfically in the context of what I am trying to do: how can I include a POJO JMS Producer in the transaction of an EJB that persists some data in a database before calling the POJO to send the message, such that if the message can't be sent due to an exception, the database transaction will roll back too? I want to send the mail asynchronously.
This is the happy path (starting within stateless session bean):
- save data to database // this works
- pull select data from the data that was persisted and place it in a custom 'message' class (really a dto)
- call the sendEmail method of the EmailQueueMessenger POJO passing it the message object.
- message is sent to the MDB to process and send the email (not part of the question, just here for completeness)
The code below works, it just won't roll back the database "persist" in the calling class if I force an error in say, a context lookup. BTW, I can't get @Resource injection to work either.
//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);
...
I have tried adding:
@TransactionAttribute(TransactionAttributeType.MANDATORY)
@Stateless
to the POJO definition but it doesn't make a difference.
FWIW I am using a separate class for the EmailQueueMessenger because there will be other parts of the app that will need to send the occasional email, so don't want to duplicated code.
Should mention that I did a test where I moved all the JMS stuff to within the first EJB and it ran correctly... but I need this to work in a separate class for use by other parts of the app.