美好的一天,
我在新用户注册后从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();
}
}
}
答案 0 :(得分:0)
@BillShannon
感谢您的帮助,我能在几个小时后解决问题。我不得不打开我的库并拿起一些关于EJB的平装书,这确实很有帮助。我注意到我的应用程序的问题是“中毒消息”。
中毒消息是一种不断重新发送的消息,因为消息使用者拒绝确认收到消息(这不是我的情况)或者编码NotificationMailer类的onMessage侦听器方法时采用的逻辑是不可接受的到GlassFish JMS MOM(我的情况)。调用“可能”抛出系统异常(例如MessageException)的方法(例如EmailUtility.sendMail())将导致中毒消息。
我的解决方案是:
在EmailUtility类中重写sendMail()方法的逻辑,以处理MessageException而不是抛出它。
重写NotificationMailer类的onMessage()侦听器方法的逻辑,以调用EmailUtility.sendMail(),而不涉及try-catch块。