我有一个非常简单的 Java webapp,它在开发系统上表现出一些非常奇怪的行为。问题从注册处理程序开始,它的实现如下:
//XXX: this shouldn't really be 'synchronized', but I've declared it as such
// for the sake of debugging this issue
public synchronized ModelAndView submitRegister(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String email = request.getParameter("email");
String pass = request.getParameter("pass");
String conf = request.getParameter("conf");
String name = request.getParameter("name");
EntityManager em = DatabaseUtil.getEntityManager(request);
//[make sure required fields are present and valid, etc.]
User user = getUserForEmail(email, em);
if (user != null) {
//[user already exists, go to error page]
}
//create the new user
em.getTransaction().begin();
try {
user = new User();
//[set fields, etc.]
em.persist(user);
//[generate e-mail message contents]
boolean validEmail = EmailUtility.sendEmail(admin, recip, subject, message, null, recip);
if (validEmail) {
em.getTransaction().commit();
//[go to 'registration successful' page]
}
em.getTransaction().rollback();
//[go to error page]
}
catch (Exception e) {
em.getTransaction().rollback();
//[go to error page]
}
}
问题出现在EmailUtility.sendEmail()
通话中。此方法的代码非常简单:
public static boolean sendEmail(String fromAddress, String to, String subject, String message, String fromHeaderValue, String toHeaderValue) {
try {
Session session = getMailSession(to);
Message mailMessage = new MimeMessage(session);
mailMessage.setFrom(new InternetAddress(fromAddress));
if (fromHeaderValue != null) {
mailMessage.setHeader("From", fromHeaderValue);
}
if (toHeaderValue != null) {
mailMessage.setHeader("To", toHeaderValue);
}
mailMessage.setHeader("Date", new Date().toString());
mailMessage.setRecipients(RecipientType.TO, InternetAddress.parse(to, false));
mailMessage.setSubject(subject);
mailMessage.setContent(message, "text/html;charset=UTF-8");
Transport.send(mailMessage);
return true;
} catch (Throwable e) {
LOG.error("Failed to send e-mail!", e);
return false;
}
}
发生的情况是,当代码到达调用时EmailUtility.sendEmail()
,不是调用该方法,而是通过 submitRegister() 递归执行。这很容易成为我见过的最奇怪的事情之一。
有一段时间我什至不相信那是实际发生的事情。但此时我已经通过同步所涉及的方法并在两种方法的每一行添加打印语句来确认它。 submitRegister()
递归,并且sendEmail()
永远不会被调用。我不知道这怎么可能。
令人沮丧的是,完全相同的代码运行在生产服务器上。仅在开发系统上才会出现此问题。
欢迎任何有关可能导致此问题的原因以及我可以做些什么来解决它的建议。