Ошибка класса DCH с JavaMail

Я пытаюсь настроить простой тест регистрации с JavaMail в Java EE 6, используя файлы jar, предоставленные Glassfish 3.1. Кажется, на эту тему существует множество вопросов, но я пока не нашел ответов, которые помогли бы. Мой тестовый код выглядит так:

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");
  }
}

мою регистрацию.файл свойств содержит следующее:

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.почта.файл 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

Я даже получаю дубликат выше для типа text / plain.

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

что я пропустила?

спасибо, Стив!--9-->

7 ответов


добавьте их перед отправкой сообщения:

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, и он работает.


Я нашел решение здесь:

http://blog.hpxn.net/2009/12/02/tomcat-java-6-and-javamail-cant-load-dch/

хотя я хотел бы узнать больше о деталях, почему это проблема, и что этот параметр-Xbootclasspath делает для исправления проблемы. Если я управляю своим классом так:

java -Djava.util.logging.config.file=logging.properties -Xbootclasspath/p:/app/glassfish-3.1/glassfish/modules/javax.mail.jar MyClass

он находит необходимые классы, и я получаю свою электронную почту. Теперь мне просто нужно выяснить, как перевести эту конфигурацию в мою Glassfish server и попробуйте более "реальный" тест из этого простого тестового случая.


в моем случае я смог решить эту проблему, добавив это до отправить():

Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );

Это было предложено в связанном блоге, поэтому, если вы хотите узнать больше деталей, прочитайте его. Спасибо Джерри ГУ за то, что он связал его здесь и оригинального блоггера.

URL:http://blog.hpxn.net/2009/12/02/tomcat-java-6-and-javamail-cant-load-dch/


вероятность высока, что если вы работаете на сервере KARAF(OSGI), вышеуказанные предложения будет трудно реализовать, поскольку у Karaf нет класса запуска или пути к классу загрузки.

Я нашел эту активацию.конфликт jar создал эту проблему .

{FUSEESB_HOME Or ServiceMIX_HOME}/etc/jre.properties was loading activation.jar .

после комментария все было гладко.

см. ссылке ниже.


хотя я хотел бы узнать больше о деталях, почему это проблема, и что этот параметр-Xbootclasspath делает для исправления проблемы.

это связано с деревом classloader. Напомним, что дочерним загрузчикам классов разрешено искать классы в Родительском загрузчике классов, но не наоборот. В вашем примере программы дерево classloader выглядит следующим образом:

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 крючок выключения бежит (JDK6+) context classloader вынужден загрузки загрузчиком что не может найти com.sun.mail.handlers.text_plain класс, потому что он находится в дочернем загрузчике классов. Из-за этого, модификации MailcapCommandMap для включения имен классов mailcap не исправит проблему. Когда вы используете -Xbootclasspath опция вы размещаете все соответствующие классы в загрузчике классов загрузки, который виден LogManager$Cleaner. Однако не изменяйте свою систему для использования -Xbootclasspath исправить это вопрос.

обновить JavaMail 1.5.3 или позже, который содержит исправление для ошибка K6552 / GH133 - используйте эргономику classloader в MailHandler. Если вы хотите обновить модуль JavaMail GlassFish, вы можете заменить glassfish-X.X/glassfish/modules/javax.mail.jar С более новой версией JavaMail.

неполное исправить применяется к JavaMail 1.4.7, чтобы установить загрузчик класса контекста в загрузчик класса, который загрузил MailHandler во время закрытия. Этот предполагается, что загрузчик классов, который загрузил MailHandler должны быть в состоянии найти код активации.

если вы не можете обновить до более новой версии JavaMail, то вы должны применить один из следующих обходных путей:

  1. очистите или закройте MailHandler перед запуском очистителя.
  2. очистите все обработчики перед запуском очистителя (т. е. веб-приложение не развертывается). Вы должны синхронизировать на LogManager и собрать все обработчики от каждого регистратора. Промывать все обработчики вне синхронизированного блока.
  3. расширьте MailHandler и переопределите close, чтобы установить и восстановить загрузчик классов контекста, если загрузчик классов контекста равен null.
  4. установите новый LogManager и переопределите reset для установки и восстановления загрузчика классов контекста, если загрузчик классов контекста равен null.
  5. установите форматер темы, чтобы установить загрузчик классов контекста, если работает очиститель.
  6. установите уровень нажима на ALL или установите емкость в 1, чтобы отправить электронное письмо для каждой записи журнала и получить спам.
  7. запустите версию Java с исправлением с помощью RFE JDK-8025251.

основная проблема в том, что LogManager$Cleaner заставляет загрузчик классов контекста равняться null перед вызовом close на каждые Handler зарегистрированы с LogManager. Лучшим выбором для LogManager было бы установить context classloader в загрузчик класса обработчика перед вызовом close, тогда в конце концов обработчики закрыты установите загрузчик класса контекста в значение null. Это все еще можно было обмануть обработчиками гнезд, но, по крайней мере, это исправило бы общий случай. Это было подано как RFE JDK-8025251 "logmanager cleaner должен использовать обработчик classloader во время закрытия".


Я столкнулся с этой проблемой сегодня, и это было связано с загрузчиком класса потока.

Если вы делаете sysout на: com.солнце.почта.дрессировщики.multipart_mixed.класс.getClassLoader()

Это может быть не то же самое, что загрузчик классов текущего потока: Нитка.currentThread().getContextClassLoader()

Я смог прийти к этому выводу, добавив следующий arg: -Djavax.активация.debug=true

после добавления этого arg я увидел, что он не смог чтобы загрузить обработчик содержимого данных (DCH) для multipart_mixed.класс.

Как вы решаете свои проблемы с загрузчиком классов, зависит от вас,но это должно заставить вас начать.


для всех, имеющих это сообщение об ошибке выше, оказалось, что в моем случае данные аутентификации были пустыми, это было связано с тем, что я отключил аутентификацию почтового сервера, мне больше не нужны имя пользователя и пароль, но пустые значения были каким-то образом проанализированы и создали отсутствующую ошибку аутентификации, которая не была поймана хорошо в Mail 1.4.0, обновление до Почты 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=""/> -->
  ...