通过EJB消息驱动Bean

时间:2017-07-16 09:46:21

标签: ejb javamail message-driven-bean

美好的一天,

我在新用户注册后从MDB onMessage方法发送电子邮件通知时遇到问题。

我正在使用队列

问题是messageListener会不断重新发送队列中的每条消息,这会导致电子邮件地址在新用户注册时获得不同的电子邮件通知(包括预期的和非预期的,旧的和新的等)。

下面是客户端代码;

    public String createAccount(String firstName, String middleName, String lastName, String username,
        String password, String confirmPassword, String email, String confirmEmail, String Organization,
        String address, String state, String country, String gRecaptchaResponse) {

    boolean verified = false;
    try {
        verified = VerifyRecaptcha.verify(gRecaptchaResponse);
    } catch (IOException ex) {
        Logger.getLogger(AdminFacade.class.getName()).log(Level.SEVERE, "Captcha palava_" + ex.getMessage(), ex);
    }

    if (verified) {
        Query q = em.createNamedQuery("Admin.findByUsername");
        q.setParameter("username", username);

        if (q.getResultList().size() > 0) {
            return "Username <" + username + "> already exists. Pls try a different username";
        }

        if (!password.equals(confirmPassword)) {
            return "Password Mis-match";
        }

        if (!email.equals(confirmEmail)) {
            return "E-mail Mis-match";
        }

        try {
            Admin admin = new Admin();

            admin.setEmail(email);
            admin.setFirstName(firstName);
            admin.setMiddleName(middleName);
            admin.setLastName(lastName);
            admin.setOrganization(Organization);
            admin.setEmail(email);
            admin.setAddress(address);
            admin.setState(state);
            admin.setCountry(country);
            admin.setExamSessionId(UniqueValueGenerator.generate());
            admin.setResultDisplay(true);

            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(password.getBytes());
            byte byteData[] = md.digest();

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }

            admin.setPassword(sb.toString());

            admin.setUsername(username);

            em.persist(admin);

            //set the password back to the literal password so that email sent will show the literal password
            admin.setPassword(password);

            QueueConnection connection = null;
            Session jmssession = null;
            MessageProducer messageProducer = null;
            try {

                connection = connectionFactory.createQueueConnection();
                jmssession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                messageProducer = jmssession.createProducer(queue);

                ObjectMessage message = jmssession.createObjectMessage();

                message.setObject(admin);
                System.out.println("Sending message attempt: ");
                System.out.println(messageProducer.getDestination().toString());
                System.out.println(messageProducer.getDeliveryMode());
                System.out.println(messageProducer.getPriority());
                messageProducer.send(message);

            } catch (JMSException ex) {
                Logger.getLogger(AdminFacade.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);

                return "Account was successfully created but it looks like we were unable to notify your email. Please check your "
                        + "mail NOW for notification  and if you can't find it, send us a mail at abc@abc.com";
            } finally {
                try {
                    connection.close();
                    jmssession.close();
                    messageProducer.close();
                    System.out.println("All Closed");
                } catch (JMSException ex) {
                    Logger.getLogger(AdminFacade.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
                }
            }

            return "Success";

        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(AdminFacade.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
            return "Something went wrong, please make sure all fields are filled correctly";
        }
    } else {
        return "You missed the Recaptcha, please retry";
    }
}

这是MDB代码;

package utility;

import entity.Admin;
import entity.Housekeeping;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.mail.MessagingException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import session.AdminFacade;
import session.HousekeepingFacade;


@MessageDriven(mappedName = "jms/notificationMailer", activationConfig = {
//    @ActivationConfigProperty(propertyName = "destinationLookup",     propertyValue = "jms/notificationMailer")
        @ActivationConfigProperty(propertyName = "acknowledgeMode",     propertyValue = "Auto-acknowledge")
,
        @ActivationConfigProperty(propertyName = "destinationType",     propertyValue = "javax.jms.Queue")
})
public class NotificationMailer implements MessageListener {

@Resource
private MessageDrivenContext mdc;

@EJB
HousekeepingFacade housekeepingFacade;
@PersistenceContext(unitName = "PU")
private EntityManager em;

public NotificationMailer() {
}

@Override
public void onMessage(Message inMessage) {
    TextMessage msg = null;
    ObjectMessage objMsg = null;

    try {
        if (inMessage instanceof TextMessage) {
            msg = (TextMessage) inMessage;
            System.out.println("MESSAGE BEAN: Message received: "
                    + msg.getText());
        }else if (inMessage instanceof ObjectMessage){
            objMsg = (ObjectMessage) inMessage;
            Admin admin = (Admin) objMsg.getObject();

                System.out.println(admin.getEmail());
            Query q2 = em.createNamedQuery("Admin.findByUsername");
            q2.setParameter("username", admin.getUsername());

            Admin u = (Admin) q2.getSingleResult();

            try {
                String recipient = admin.getEmail();
                String subject = "Account Creation Confirmation";
                String content = "my content";

                Housekeeping housekeeping = housekeepingFacade.findAll().get(0);
                EmailUtility.sendEmail(EmailUtility.HOST, EmailUtility.PORT, EmailUtility.USERNAME, housekeeping.getNoReplyPw(), recipient, subject, content, true);
                EmailUtility.sendEmail(EmailUtility.HOST, EmailUtility.PORT, EmailUtility.USERNAME, housekeeping.getNoReplyPw(), "abc@abc.com", "New Admin Sign-up", "A new admin with account name: " + u.getUsername() + " and email " + u.getEmail() + " just signed up", false);
                System.out.println("Done sending");
            } catch (MessagingException ex) {                    
                String errMsg = "Account was successfully created but it looks like we were unable to notify your email. Please check your "
                        + "mail NOW for notification  and if you can't find it, send us a mail at support@abc.com";
                Logger.getLogger(AdminFacade.class.getName()).log(Level.SEVERE, ex.getMessage()+"___"+errMsg, ex);
            }

        }else {
            System.out.println("Message of wrong type: "
                    + inMessage.getClass().getName());
        }
    } catch (JMSException e) {
        e.printStackTrace();
        mdc.setRollbackOnly();
    } catch (Throwable te) {
        te.printStackTrace();
    }

}   

}

1 个答案:

答案 0 :(得分:0)

@BillShannon

感谢您的帮助,我能在几个小时后解决问题。我不得不打开我的库并拿起一些关于EJB的平装书,这确实很有帮助。我注意到我的应用程序的问题是“中毒消息”。

中毒消息是一种不断重新发送的消息,因为消息使用者拒绝确认收到消息(这不是我的情况)或者编码NotificationMailer类的onMessage侦听器方法时采用的逻辑是不可接受的到GlassFish JMS MOM(我的情况)。调用“可能”抛出系统异常(例如MessageException)的方法(例如EmailUtility.sendMail())将导致中毒消息。

我的解决方案是:

  1. 在EmailUtility类中重写sendMail()方法的逻辑,以处理MessageException而不是抛出它。

  2. 重写NotificationMailer类的onMessage()侦听器方法的逻辑,以调用EmailUtility.sendMail(),而不涉及try-catch块。