Logging JavaMail中的DCH类错误

Logging JavaMail中的DCH类错误,logging,glassfish,jakarta-mail,java-ee-6,Logging,Glassfish,Jakarta Mail,Java Ee 6,我正试图使用Glassfish 3.1提供的jar文件,在JavaEE6中使用JavaMail设置一个简单的日志测试。在这个问题上似乎有很多问题,但我还没有找到任何有帮助的答案。我的测试代码如下所示: import java.util.logging.Logger; public class MyClass { private static final Logger LOGGER = Logger.getLogger("MyClass"); public static void ma

我正试图使用Glassfish 3.1提供的jar文件,在JavaEE6中使用JavaMail设置一个简单的日志测试。在这个问题上似乎有很多问题,但我还没有找到任何有帮助的答案。我的测试代码如下所示:

import java.util.logging.Logger;

public class MyClass {
  private static final Logger LOGGER = Logger.getLogger("MyClass");

  public static void main(String[] args) {
    LOGGER.severe("This is a test");
  }
}
java -Djava.util.logging.config.file=logging.properties -Xbootclasspath/p:/app/glassfish-3.1/glassfish/modules/javax.mail.jar MyClass
Running under JDK6, JDK7, and JDK8
+---Boot ClassLoader--+
| java.util.logging.* |
| javax.activation .* |
+---------------------+
          ^
          |
+-----System ClassLoader------+
| javax.mail.*                |
| com.sun.mail.handlers.*     |
| com.sun.mail.util.logging.* |
+-----------------------------+
My logging.properties文件包含以下内容:

com.sun.mail.util.logging.MailHandler.mail.smtp.host={my mail hub FQDN}
com.sun.mail.util.logging.MailHandler.mail.smtp.port=25
com.sun.mail.util.logging.MailHandler.mail.to={me}
com.sun.mail.util.logging.MailHandler.mail.from={support address}
com.sun.mail.util.logging.MailHandler.level=WARNING
com.sun.mail.util.logging.MailHandler.verify=local
com.sun.mail.util.logging.MailHandler.subject=Application Error
com.sun.mail.util.logging.MailHandler.formatter=java.util.logging.SimpleFormatter
我使用以下方法构建类:

javac -cp $AS_INSTALL/glassfish/modules/javax.mail.jar:$AS_INSTALL/install/lib/external/jaxb/activation.jar:. MyClass.java
然后,我使用以下命令运行程序:

java -cp $AS_INSTALL/glassfish/modules/javax.mail.jar:$AS_INSTALL/install/lib/external/jaxb/activation.jar:. -Djava.util.logging.config.file=logging.properties MyClass
这将导致以下错误:

Sep 22, 2011 4:19:25 PM MyClass main
SEVERE: This is a test
java.util.logging.ErrorManager: 3: SEVERE: no object DCH for MIME type multipart/mixed;
        boundary="----=_Part_1_26867996.1316722766145"
javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed;
        boundary="----=_Part_1_26867996.1316722766145"
        at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:877)
        at javax.activation.DataHandler.writeTo(DataHandler.java:302)
        at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1476)
        at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1772)
        at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1748)
        at com.sun.mail.util.logging.MailHandler.toRawString(MailHandler.java:2196)
        at com.sun.mail.util.logging.MailHandler.send(MailHandler.java:1597)
        at com.sun.mail.util.logging.MailHandler.close(MailHandler.java:552)
        at java.util.logging.LogManager.resetLogger(LogManager.java:693)
        at java.util.logging.LogManager.reset(LogManager.java:676)
        at java.util.logging.LogManager$Cleaner.run(LogManager.java:221)

javax.mail.MessagingException: IOException while sending message;
  nested exception is:
        javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed;
        boundary="----=_Part_1_26867996.1316722766145"
        at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1141)
        at javax.mail.Transport.send0(Transport.java:195)
        at javax.mail.Transport.send(Transport.java:124)
        at com.sun.mail.util.logging.MailHandler.send(MailHandler.java:1594)
        at com.sun.mail.util.logging.MailHandler.close(MailHandler.java:552)
        at java.util.logging.LogManager.resetLogger(LogManager.java:693)
        at java.util.logging.LogManager.reset(LogManager.java:676)
        at java.util.logging.LogManager$Cleaner.run(LogManager.java:221)
Caused by: javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed;
        boundary="----=_Part_1_26867996.1316722766145"
        at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:877)
        at javax.activation.DataHandler.writeTo(DataHandler.java:302)
        at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1476)
        at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1772)
        at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1099)
        ... 7 more
我已经验证了javax.mail.jar文件包含多部分处理程序:

unzip -l $AS_INSTALL/glassfish/modules/javax.mail.jar | grep multipart
     2617  01-14-2011 15:37   com/sun/mail/handlers/multipart_mixed.class
我甚至在启用激活调试的情况下运行了该程序。这向我展示了以下相关部分:

parse: multipart/*;;            x-java-content-handler=com.sun.mail.handlers.multipart_mixed; x-java-fallback-entry=true
  Type: multipart/*
    Command: content-handler, Class: com.sun.mail.handlers.multipart_mixed

MailcapCommandMap: createDataContentHandler for multipart/mixed
  search DB #1
  search DB #2
  search fallback DB #1
    got content-handler
      class com.sun.mail.handlers.multipart_mixed
Can't load DCH com.sun.mail.handlers.multipart_mixed; Exception: java.lang.ClassNotFoundException: com/sun/mail/handlers/multipart_mixed
我甚至得到了上面的文本/纯文本的副本

MailcapCommandMap: createDataContentHandler for text/plain
  search DB #1
    got content-handler
      class com.sun.mail.handlers.text_plain
Can't load DCH com.sun.mail.handlers.text_plain; Exception: java.lang.ClassNotFoundException: com/sun/mail/handlers/text_plain
我错过了什么

谢谢,
史蒂夫

我在这里找到了解决方案:

虽然我很想知道更多关于为什么这是一个问题背后的细节,以及这个-Xbootclasspath选项是如何纠正这个问题的。如果我像这样运行我的类:

import java.util.logging.Logger;

public class MyClass {
  private static final Logger LOGGER = Logger.getLogger("MyClass");

  public static void main(String[] args) {
    LOGGER.severe("This is a test");
  }
}
java -Djava.util.logging.config.file=logging.properties -Xbootclasspath/p:/app/glassfish-3.1/glassfish/modules/javax.mail.jar MyClass
Running under JDK6, JDK7, and JDK8
+---Boot ClassLoader--+
| java.util.logging.* |
| javax.activation .* |
+---------------------+
          ^
          |
+-----System ClassLoader------+
| javax.mail.*                |
| com.sun.mail.handlers.*     |
| com.sun.mail.util.logging.* |
+-----------------------------+

它找到了必要的课程,我收到了电子邮件。现在,我只需要弄清楚如何将此配置转换到Glassfish服务器中,并从这个简单的测试用例中尝试一个更“真实”的测试。

在发送消息之前添加以下内容:

MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
        mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
        mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
        mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
        mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
        mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
        CommandMap.setDefaultCommandMap(mc);

我在我的Android应用程序中遇到了这个问题,它可以正常工作。

在我的例子中,我可以通过在发送之前添加这个来解决这个问题()

这是链接博客中的建议,所以如果你想知道更多细节,请阅读。感谢Jerry Gu将其链接到这里和原创博主


URL:

如果您使用的是KARAF(OSGI)服务器,则上述建议很难实现,因为KARAF没有启动类或启动类路径

我发现activation.jar冲突造成了这个问题

{FUSEESB_HOME Or ServiceMIX_HOME}/etc/jre.properties was loading activation.jar .
有一次,一切都很顺利

请参阅

虽然我很想知道更多关于为什么这是一个问题背后的细节,以及这个-Xbootclasspath选项是如何纠正这个问题的

<appender name="ALARM_MAIL" class="my.utils.SMTPAppender">
  <!-- remove this line: <param name="SMTPUsername" value=""/> -->
  <!-- remove this line: <param name="SMTPPassword" value=""/> -->
  ...
它与类加载器树有关。回想一下,允许子类加载器在父类加载器中查找类,但不能反过来查找。在示例程序中,classloader树如下所示:

import java.util.logging.Logger;

public class MyClass {
  private static final Logger LOGGER = Logger.getLogger("MyClass");

  public static void main(String[] args) {
    LOGGER.severe("This is a test");
  }
}
java -Djava.util.logging.config.file=logging.properties -Xbootclasspath/p:/app/glassfish-3.1/glassfish/modules/javax.mail.jar MyClass
Running under JDK6, JDK7, and JDK8
+---Boot ClassLoader--+
| java.util.logging.* |
| javax.activation .* |
+---------------------+
          ^
          |
+-----System ClassLoader------+
| javax.mail.*                |
| com.sun.mail.handlers.*     |
| com.sun.mail.util.logging.* |
+-----------------------------+
当运行
LogManager$Cleaner
shutdown钩子(JDK6+)时,将强制执行,因为它位于子类加载器中,所以无法定位
com.sun.mail.handlers.text\u plain
类。因此,我们无法解决问题。当您使用
-Xbootclasspath
选项时,您正在将所有相关类放置在引导类加载程序中,
LogManager$Cleaner
可见。但是,不要修改系统以使用
-Xbootclasspath
修复此问题

相反,请升级到或更高版本,其中包含针对的修复程序。如果您想升级GlassFish的JavaMail模块,可以用更新版本的JavaMail替换
GlassFish-X.X/GlassFish/modules/javax.mail.jar

应用于JavaMail 1.4.7的不完整操作是将上下文类加载器设置为在关闭期间加载
MailHandler
的类加载器。假设加载
MailHandler
的类加载器应该能够找到激活代码

如果无法升级到较新版本的JavaMail,则必须应用以下解决方法之一:

  • 在清理程序运行之前,请刷新或关闭邮件处理程序。
  • 在运行清理程序之前刷新所有处理程序(即web应用程序取消部署)。您必须在LogManager上同步,并从每个记录器收集所有处理程序。刷新同步块外部的所有处理程序。
  • 如果上下文类加载器为空,则扩展MailHandler并覆盖close以设置和恢复上下文类加载器。
  • 安装一个新的LogManager并覆盖
    reset
    ,以便在上下文类加载器为空时设置和恢复上下文类加载器。
  • 如果cleaner正在运行,请安装主题格式化程序以设置上下文类加载器。
  • 将推送级别设置为
    ALL
    ,或将容量设置为1,以便为每个日志记录发送电子邮件并收到垃圾邮件。
  • 运行在带有RFE JDK-8025251补丁的Java版本上。
    主要问题是,
    LogManager$Cleaner
    强制上下文类加载器在调用
    close
    之前为空,然后对每个注册到
    LogManager
    处理程序
    。LogManager更好的选择是在调用close之前将上下文类加载器设置为处理程序类加载器,然后在关闭所有处理程序之后将上下文类加载器设置为null。这仍然可能被嵌套处理程序所愚弄,但至少它已经修复了常见情况。这是作为RFE“LogManager cleaner应在关闭期间使用handler classloader”归档的。

    对于所有出现上述错误消息的人,结果证明,在我的情况下,身份验证数据是空的,这是因为我关闭了邮件服务器身份验证,我不再需要用户名和密码,但是空值被以某种方式解析,并创建了一个丢失的身份验证错误,该错误在Mail 1.4.0中没有很好地被捕获,更新到Mail 1.4.7删除下面的两个参数条目解决了问题

    <appender name="ALARM_MAIL" class="my.utils.SMTPAppender">
      <!-- remove this line: <param name="SMTPUsername" value=""/> -->
      <!-- remove this line: <param name="SMTPPassword" value=""/> -->
      ...
    
    
    ...
    
    我今天碰到了这个问题,它与线程的类加载器有关

    如果您在上执行sysout操作: com.sun.mail.handlers.multipart_mixed.class.getClassLoader()

    它可能与当前线程的类加载器不同: Thread.currentThread().getContextClassLoader()

    我可以通过添加以下参数得出这一结论: -Djavax.activation.debug=true

    添加该参数后,我发现它无法为multipart_mixed.class加载数据内容处理程序(DCH)


    如何解决类加载器问题取决于您,但这应该可以让您开始。

    我要补充的是,这是一个Solaris 10系统