開発システムで非常に奇妙な動作を示している非常に単純なJavaWebアプリがあります。問題は、登録ハンドラーから始まります。これは、次のように強制されます。
//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()を介して実行が繰り返されます。これは、私が今まで見た中で最も奇妙なことの1つです。
しばらくの間、私はそれが実際に起こっていることだとさえ信じていませんでした。しかし、この時点で、関連するメソッドを同期し、両方のメソッドのすべての行にprintステートメントを追加することで確認しました。 submitRegister()
再発し、sendEmail()
呼び出されることはありません。これがどのように可能であるのか私にはわかりません。
苛立たしいことに、まったく同じコードが本番サーバーで実行されるのとまったく同じように実行されます。この問題が発生するのは開発システムのみです。
この問題を引き起こしている可能性のあるものと、それを修正するために私ができることに関する提案は大歓迎です。