java.lang.ClassCastException: com.sun.mail.handlers.multipart_mixed cannot be cast to javax.activation.DataContentHandler

Simone Sorgon :

The line part.writeTo(out); throws java.lang.ClassCastException:

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

private static void getBodyAsRFC822(
        MimePart part, boolean ignoreHeaders, ByteArrayOutputStreamout) {
    try {
        out.reset();

        if (ignoreHeaders) {
            OutputStream os = MimeUtility.encode(out, part.getEncoding());
            part.getDataHandler().writeTo(os);
            os.close();
        } else {
            part.writeTo(out);
            out.close();
        }
    }
    catch (Exception e) {
        _log.error(e);
    }
}

This is my build.gradle

compileOnly group: 'com.liferay', name: 'com.liferay.portal.instance.lifecycle', version: '2.0.0'
compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "2.46.0"
compileOnly group: "org.osgi", name: "org.osgi.core", version: "6.0.0"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.3.0"

compileInclude group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
compileInclude group: 'org.apache.mina', name: 'mina-core', version: '2.0.16'
compileInclude group: 'javax.mail', name: 'mail', version: '1.4'
compileInclude group: "javax.servlet", name: "servlet-api", version: "2.5"

But multipart_mixed implements DataContentHandler, so it should be castable. Why isn't it?

Olaf Kock :

Whenever a subclass apparently can't be typecasted to its legitimate superclass, you have duplicate classes, loaded by different classloaders. Find where you load the activation (superclass) classes, eliminate all but one (typically you'll need to eliminate the one class that your own project brings) and use the provided one from the framework.

The Exception message names the classes in question but omits the classloaders participating in the game, which is why the message, on first attempt to understand it, doesn't make much sense. As soon as you know about multiple classloaders, thus multiple instances of javax.activation.DataContentHandler, it makes more sense.

Edit: With the compileInclude statements in your build.gradle, you're effectively bundling all your dependencies into your own jar file. But the framework has its own version of these classes, and while they all have the same name, they'll now be different versions (not only numeric), loaded through different classloaders. You should only use compileInclude if you clearly are dependent on something that you'll never find in the OSGi runtime. Instead, use compileOnly or compile as default, and deploy the additional dependencies to the runtime, together with your module.

Check this article for a detailed description of what you've done.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=150820&siteId=1