0

We need to send mail from a log handler in GlassFish v3.1.2.2.

We've tried to use smtphandler-0.6 and -0.7 with limited success. We install the jarfile to domain/lib/ext, and configure smtphandler's properties in domain/config/logging.properties. We've tried two ways of satisfying smtphandler's reliance on mail imports: 1) Editing its manifest classpath to point to ../../../../modules/javax.mail.jar, and 2) Putting javax.mail.jar in domain/lib/ext alongside the smtphandler jar. (We prefer the former approach so that the same javamail classes are used throughout the system. But it seems to make no difference, no worky either way.)

With either of these arrangements the behavior is the same:

  • The handler loads ok as shown by the JVM's verbose:class output.
  • Sometimes it sends mail for errors and warnings that occur during domain startup (like the expired certificate). Other times it fails as described below before ever sending mail.
  • It always fails once we've deployed our application and logged some application errors. We can tell that the handler is invoked - that's evidenced by the debugger and some primitive System.out "logging".

The root problem is a NoSuchMethodException: com.sun.mail.smtp.SMTPTransport.[init](Session, URLName). The failure to find the c'tor means the transport object can't be created; that eventually manifests as a NoSuchProtocolException.

We can see that the SMTPTransport class is loaded and that it has the requested c'tor. Our best theory is that class loading is somehow involved, but we've not been able to figure out exactly how. (Yet. We're working that angle now.)

Questions:

  • Are we deploying the handler to the correct location (domain/lib/ext) ?
  • Why does it (sometimes) send mail during an (empty, no apps) domain startup, but fail for logs emitted by our application? That's a race condition, surely, but what are those threads doing that occasionally works for a bit then reliably fails?
  • Are we right to think that all these indications together imply a class loading issue?

We've reproduced these symptoms on GlassFish versions 3.1.2.2 and 4, with JavaMail 1.4.4 and 1.5.

Thanks in advance for any help.

4

1 回答 1

0

尝试在 GlassFish 服务器中安装日志处理程序时,似乎报告了此 NoSuchMethodException 的错误。JavaMail 团队在Bug K6668 |下提出了这个问题。GH144 - 跳过JavaMail 1.5.3中修复的不可用的 Store 和 Transport 类。升级 glassfish 中的 JavaMail 模块和部署的所有其他副本应该可以解决此问题。使用“glassfish/bin/asadmin start-domain -v”启动 glassfish 也很有帮助,这样您就可以看到所有引导消息。

• 我们是否将处理程序部署到正确的位置(域/lib/ext)

是的。您可以部署到 domain/lib/ext 但您必须包含 JavaMail 1.5.3 才能找​​到正确的传输服务。否则,您可以将 jar 部署到模块目录并添加HK2 元数据以使 smtphandler 看起来像一个服务。这可以通过包含新 jar 或修改现有的 smtphandler jar 来完成。

对于 GlassFish 3,META-INF/inhabitants/default必须添加包含以下内容的文件:

class=smtphandler.SMTPHandler,index=java.util.logging.Handler

对于 GlassFish 4,META-INF/hk2-locator/default必须添加包含以下内容的文件:

[smtphandler.SMTPHandler]
contract={java.util.logging.Handler}
scope=javax.inject.Singleton

glassfish/modules然后该 jar 必须与升级 javax.mail.jar 一起放入该文件夹中。

另一种选择是将 smtphandler 子类化,使其看起来像 HK2 日志处理程序服务,并添加一个 preDestroy 方法以在关闭时触发电子邮件。这在 Oracle GlassFish Server 3.1 管理指南第一部分第 7 节标题为添加自定义日志记录处理程序中进行了描述。

在 GlassFish 4 中,有两种不同的方法可以在 logging.properties 中定位处理程序。放置的处理程序domain/lib/ext使用属性文件中的标准handlers键。glassfish/modules作为 HK2 服务放置的处理程序是使用handlerServices 属性文件中的键加载的。

#GF3 ext/endorsed or OSGI.  GF4 ext/endorsed only.
handlers=smtphandler.SMTPHandler

#GF4 OSGI only, 'handlerServices' should not contain any whitespace characters between handlers.
handlerServices=com.sun.enterprise.server.logging.GFFileHandler,smtphandler.SMTPHandler

•为什么它(有时)在(空的,没有应用程序)域启动期间发送邮件,但对于我们的应用程序发出的日志却失败了?当然,这是一种竞争条件,但是那些偶尔会工作一段时间然后可靠地失败的线程是做什么的?

GF 记录的消息与您的 Web 应用程序之间的上下文类加载器差异。CCL 在 JavaMail 中用于定位传输。修补 'sendBuffer' 方法应该可以解决问题:

@Override
protected void sendBuffer() {
    final Thread thread = Thread.currentThread();
    ClassLoader ccl = null;
    try {
        ccl = thread.getContextClassLoader();
        thread.setContextClassLoader(
                javax.mail.Transport.class.getClassLoader());
    } catch (SecurityException ignore) {
    }
    try {
        super.sendBuffer();
    } finally {
        try {
            thread.getContextClassLoader();
            thread.setContextClassLoader(ccl);
        } catch (SecurityException ignore) {
        }
    }
}

• 我们认为所有这些迹象都意味着类加载问题是否正确?

是的。真正使这项工作正常进行的唯一方法是对 smtphandler 进行子类化或修补,使其看起来像 HK2 组件并修改 CCL。

我们需要从 GlassFish v3.1.2.2 中的日志处理程序发送邮件。我们尝试使用 smtphandler-0.6 和 -0.7,但效果有限。

免责声明:我是JavaMail 项目中包含的MailHandler的内容开发人员。

smtphandler 的替代方案是com.sun.mail.util.logging.MailHandler包含在 JavaMail 参考实现中。

在 GlassFish 4 下,您必须拥有glassfish/modules/javax.mail.jarJavaMail 1.5.3 或更新版本可从JavaMail API 主页下载更新版本,并可用于替换 GlassFish 捆绑的版本。

接下来,您必须修改logging.properties域。这是一个示例配置,您可以将其包括在内以帮助您入门。

#Ensure no whitespace between handler class names.
handlerServices=com.sun.enterprise.server.logging.GFFileHandler,com.sun.mail.util.logging.MailHandler    
com.sun.mail.util.logging.MailHandler.subject=com.sun.mail.util.logging.CollectorFormatter
#com.sun.mail.util.logging.CollectorFormatter.format=GlassFish 4.x:{0}{1}{2}{4,choice,-1#|0#|0<... {4,number,integer} more}
#com.sun.mail.util.logging.CompactFormatter.format=[%4$-7.7s] %7$#.140s
com.sun.mail.util.logging.MailHandler.level=WARNING
com.sun.mail.util.logging.MailHandler.filter=com.sun.mail.util.logging.DurationFilter
com.sun.mail.util.logging.MailHandler.pushLevel=WARNING
com.sun.mail.util.logging.MailHandler.mail.smtp.host=some-smtp-host
#com.sun.mail.util.logging.MailHandler.mail.user=some-user
#com.sun.mail.util.logging.MailHandler.authenticator=some-password
com.sun.mail.util.logging.MailHandler.mail.from=app@server.com
#com.sun.mail.util.logging.MailHandler.mail.sender=team@list.com
com.sun.mail.util.logging.MailHandler.mail.to=devs@bugfixers.com
com.sun.mail.util.logging.MailHandler.verify=resolve
com.sun.mail.util.logging.MailHandler.mail.smtp.quitwait=false
com.sun.mail.util.logging.MailHandler.mail.smtps.quitwait=false
com.sun.mail.util.logging.MailHandler.mail.smtp.connectiontimeout=45000
com.sun.mail.util.logging.MailHandler.mail.smtps.connectiontimeout=45000
com.sun.mail.util.logging.MailHandler.mail.smtp.timeout=45000
com.sun.mail.util.logging.MailHandler.mail.smtps.timeout=45000

对于 GlassFish 3,您必须在domain/lib/extor下安装 JavaMail (javax.mail.jar)glassfish/lib/endorsed并测试这不会破坏您的任何应用程序。这个类加载器配置也可以在 GlassFish 4 下工作,并允许将 MailHandler 与MemoryHandler结合起来,这可以模拟 smtphandler 的行为。

接下来,您必须修改logging.properties域。您可以使用与 GlassFish 4 相同的示例,但您必须使用标准handlers标签而不是handlerServices.

handlers=java.util.logging.MemoryHandler
java.util.logging.MemoryHandler.target=com.sun.mail.util.logging.MailHandler
java.util.logging.MemoryHandler.size=512
java.util.logging.MemoryHandler.level=INFO
java.util.logging.MemoryHandler.push=WARNING
com.sun.mail.util.logging.MailHandler.capacity=512
com.sun.mail.util.logging.MailHandler.level=INFO
com.sun.mail.util.logging.MailHandler.pushLevel=WARNING
com.sun.mail.util.logging.MailHandler.filter=com.sun.mail.util.logging.DurationFilter
com.sun.mail.util.logging.DurationFilter.records=512
com.sun.mail.util.logging.DurationFilter.duration=5*60*1000
于 2013-10-11T19:33:24.870 回答