views:

192

answers:

2

I'm upgrading from ColdFusion 8 to ColdFusion 9. I have a Java class that I call from CF which reads and parses the contents of an mbox mailbox file. The class works fine with CF 8, but it's throwing an error in CF 9. The error is:

com.sun.mail.handlers.text_plain cannot be cast to javax.activation.DataContentHandler

The error is happening at the point where the Java code is calling the getContent() function from javax.mail.internet.MimeMessage. Based on the MIME type of the message, I'm casting the return value of getContent() to one of String, MimeBodyPart, or Part.

Does anyone have any ideas how to fix this?

Here's my Java function:

public String getHtmlContent(Part p) throws IOException, MessagingException {
    StringBuffer szContent = new StringBuffer();
    if ( p.isMimeType("text/plain") ) 
    {
        szContent.append( contentToHtml( (String) p.getContent() ) );           
    }
    else if ( p.isMimeType("multipart/*") ) 
    {
        Multipart multipart = (Multipart) p.getContent();
        for ( int i = 0, n = multipart.getCount(); i < n; i++ ) {
            szContent.append( getHtmlContent((MimeBodyPart) multipart.getBodyPart( i )));               
        }
    }
    else if ( p.isMimeType("message/rfc822") ) 
    {
        szContent.append( getHtmlContent( (Part) p.getContent() ));             
    }
    else 
    {
        throw new RuntimeException( "Cannot determine message content." );
    }
    return szContent.toString();
}

And here's the Java stack trace:

javax.activation.MailcapCommandMap.getDataContentHandler(MailcapCommandMap.java:581) at javax.activation.MailcapCommandMap.createDataContentHandler(MailcapCommandMap.java:535) at javax.activation.CommandMap.createDataContentHandler(CommandMap.java:191) at javax.activation.DataHandler.getDataContentHandler(DataHandler.java:594) at javax.activation.DataHandler.getContent(DataHandler.java:522) at javax.mail.internet.MimeMessage.getContent(MimeMessage.java:1395) at its.util.MBoxMessage.getHtmlContent(MBoxMessage.java:166) at its.util.MBoxMessage.getHtmlContent(MBoxMessage.java:159) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at coldfusion.runtime.StructBean.invoke(StructBean.java:502) at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2393) at cfmessage2ecfm263917690.runPage(\web.shares\web\goat\cf\courses\classlist\message.cfm:216) at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231) at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416) at coldfusion.filter.CfincludeFilter.invoke(CfincludeFilter.java:65) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:363) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40) at coldfusion.filter.PathFilter.invoke(PathFilter.java:87) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:53) at coldfusion.CfmServlet.service(CfmServlet.java:200) at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89) at jrun.servlet.FilterChain.doFilter(FilterChain.java:86) at com.intergral.fusionreactor.filter.FusionReactorFilter.B(Unknown Source) at com.intergral.fusionreactor.filter.FusionReactorFilter.A(Unknown Source) at com.intergral.fusionreactor.filter.FusionReactorFilter.doFilter(Unknown Source) at jrun.servlet.FilterChain.doFilter(FilterChain.java:94) at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46) at jrun.servlet.FilterChain.doFilter(FilterChain.java:94) at jrun.servlet.FilterChain.service(FilterChain.java:101) at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106) at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42) at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286) at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543) at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203) at jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320) at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428) at jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266) at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

+2  A: 

This sounds like a classloader issue. Sometimes a ClassCastException like this one results from the original object's class (com.sun.mail.handlers.text_plain) coming from one classloader and the target class (DataContentHandler) coming from another. Despite the classes being identical, the jvm detects that they are from different class loaders thus refuses to cast. The error message in this case is not very informative.

It can happen due to jars being mixed up, maybe one version of JavaMail in your webapp folder and another in < jdk_home>/jre/lib/endorsed or something like that.

  • I am not familiar with ColdFusion so this is just a guess, but did the upgrade involve a jdk upgrade as well?
  • Did anything in the classloaders hierarchy change? Maybe a parent first vs. parent last policy of webapps (like is supported in Weblogic and WebSphere)?.
  • Where do you have JavaMail and Activation jars? Do you have those jars in your webapp?
Yoni
@Yoni - +1. From what I can tell, they changed the way the mail jars are loaded in CF9. In CF8, they were loaded by CF's "App Server class loader". That is the same loader used when you create java objects from within CF code ie createObject("java", ..). But in CF9, I believe the mail jars are loaded by CF's "bootstrap" class loader. So that would explain the cast error. But I am not sure how one would fix that ..
Leigh
A: 

I removed the activation.jar file from CF's lib folder. The javax.activation classes are duplicated in jrun.jar, and both JAR file are in CF's classpath. It looks like the classes are newer in activation.jar, but removing them did the trick for the custom class. Hopefully nothing in CF is relying on the newer classes.

stomcavage
@stomcavage - They actually exist in several jars (jdk's rt.jar etc..). At least some version anyway. I am always very leery of removing jars used by CF without knowing the impact it will have ..
Leigh