我有一个非常简单的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()的调用时,而不是调用该方法,执行通过commitRegister()递归进行。这很容易是我见过的最奇怪的事情之一。

有一阵子我什至都不相信那是实际发生的事情。但目前为止,我已经通过同步涉及的方法并在这两种方法的每一行上添加了打印语句来确认这一点。 submitRegister()递归,并且永远不会调用sendEmail()。我不知道这怎么可能。

令人沮丧的是,完全相同的代码运行与在生产服务器上应运行的代码相同。仅在开发系统上出现此问题。

欢迎提供有关可能导致此问题的任何建议以及我可以采取的解决措施。

最佳答案

您是对的,这是不可能的:)
如果您不喜欢调试并查看会发生什么,我建议您剥离所有其他代码,放入大量日志记录。从类似以下内容开始:

public synchronized ModelAndView submitRegister(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    LOG.debug("submitRegister: " + this.toString);
    EmailUtility.sendEmail("[email protected]", "[email protected]", "subject", "message", "from", "to");
}

public static boolean sendEmail(String fromAddress, String to, String subject, String message, String fromHeaderValue, String toHeaderValue) {
    LOG.debug("sendEmail: " + this.toString());
}


toString将向您显示所涉及的类。
我的猜测是:


您的第一次呼叫失败,因此将永远不会调用sendEmail
submitRegister多次被其他人触发,而不是由EmailUtility.sendEmail语句触发。


如果您可以使用剥离后的版本,请开始放回您的代码,一次放心地查看所有错误之处:)

关于java - 这个执行流程怎么可能?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12524668/

10-08 21:52