我们使用Javamailapi创建了一个侦听器来读取电子邮件收件箱中新添加的消息。一旦侦听器接收到新消息,我们将尝试获取所有标头信息以及内容部分。为了解析内容,我们已经编写了一个合适的解析逻辑,它对所有类型的内容(文本、html、多部分等)都能很好地工作。
private String getText(Part p) throws MessagingException, IOException {
if (p.isMimeType("text/*")) {
String s = (String) p.getContent();
return s;
}
if (p.isMimeType("multipart/alternative")) {
// prefer html text over plain text
Multipart mp = (Multipart) p.getContent();
String text = null;
for (int i = 0; i < mp.getCount(); i++) {
Part bp = mp.getBodyPart(i);
if (bp.isMimeType("text/plain")) {
if (text == null){
text = getText(bp);
return text;
}
} else if (bp.isMimeType("text/html")) {
String s = getText(bp);
if (s != null)
return s;
} else {
return getText(bp);
}
}
return text;
} else if (p.isMimeType("multipart/*")) {
Multipart mp = (Multipart) p.getContent();
for (int i = 0; i < mp.getCount(); i++) {
String s = getText(mp.getBodyPart(i));
if (s != null)
return s;
}
}
return null;
}
上面的监听器和解析,我们在一个部署在tomcat容器(版本-Apachetomcat8.0.35)中的web应用程序中运行
当IMAP连接的会话超时一段时间后,我们将通过编程重新启动侦听器。现在,侦听器可以将新添加的消息读取到收件箱中,但消息内容解析失败,出现以下异常。我们尝试了多种方法来解决这个问题,但都没有成功。以下是异常堆栈跟踪
25-Mar-2016 14:08:10.158 INFO [JavaMail-EventQueue] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load [com.sun.mail.handlers.multipart_mixed]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [com.sun.mail.handlers.multipart_mixed]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1328)
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1316)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1181)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1142)
at javax.activation.MailcapCommandMap.getDataContentHandler(MailcapCommandMap.java:582)
at javax.activation.MailcapCommandMap.createDataContentHandler(MailcapCommandMap.java:560)
at javax.activation.CommandMap.createDataContentHandler(CommandMap.java:221)
at javax.activation.DataHandler.getDataContentHandler(DataHandler.java:615)
at javax.activation.DataHandler.getContent(DataHandler.java:542)
at javax.mail.internet.MimeMessage.getContent(MimeMessage.java:1419)
at omniquo.awe.util.MailUtil.readMailBody(MailUtil.java:152)
at omniquo.awe.activitiservice.MailListner$MailThreadListener$2.messagesAdded(MailListner.java:165)
at javax.mail.event.MessageCountEvent.dispatch(MessageCountEvent.java:150)
at javax.mail.EventQueue.run(EventQueue.java:134)
at java.lang.Thread.run(Thread.java:745)
Unable to parse Email com.sun.mail.imap.IMAPInputStream cannot be cast to javax.mail.internet.MimeMultipart
java.lang.ClassCastException: com.sun.mail.imap.IMAPInputStream cannot be cast to javax.mail.internet.MimeMultipart
at omniquo.awe.util.MailUtil.readMailBody(MailUtil.java:152)
at omniquo.awe.activitiservice.MailListner$MailThreadListener$2.messagesAdded(MailListner.java:165)
at javax.mail.event.MessageCountEvent.dispatch(MessageCountEvent.java:150)
at javax.mail.EventQueue.run(EventQueue.java:134)
at java.lang.Thread.run(Thread.java:745)
我们需要一个具体的解决方案来解决这个问题。我们正在使用以下环境和api版本
JDK-1.8.0_65,Tomcat-8.035,Java邮件-1.5.5,弹簧-4
很难理解如果没有任何更改,为什么会开始失败。你真的需要弄清楚发生了什么变化。您使用的是JDK还是Tomcat的新版本?
您所说的"通过编程重新启动侦听器"究竟是什么意思?您正在重新启动Tomcat服务器吗?
这个问题的出现通常是因为JavaBeans激活框架(JAF,现在是JDK的一部分)无法找到描述什么Java类用于什么MIME类型的配置文件。此配置文件是JavaMail jar文件的一部分。如果你的应用程序被更改,而这个文件丢失了,那就可以解释了。如果你使用了一些不寻常的类加载方案,也可能是由于ClassLoader的问题。
如果您正在重新加载Web应用程序,那么javax.mail.EventQueue将捕获第一个Web应用程序类加载器。当创建新线程时,上下文类加载器被设置为父线程的上下文类加载器。
synchronized void enqueue(MailEvent event, Vector vector) {
// if this is the first event, create the queue and start the event task
if (q == null) {
q = new LinkedBlockingQueue<QueueElement>();
if (executor != null) {
executor.execute(this);
} else {
Thread qThread = new Thread(this, "JavaMail-EventQueue");
qThread.setDaemon(true); // not a user thread
qThread.start();
}
}
q.add(new QueueElement(event, vector));
}
修改MessageCountListener以设置上下文类加载器:
public void messagesAdded(MessageCountEvent e) {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
//Your existing code....
}