Hi Stephan,
I think the dynamic import is a nice workaround short term.
I think 3 (with a handler) is more robust long term. WDYT ?
Regards
JB
On 11/02/2019 12:35, Siano, Stephan wrote:
> Hi,
>
> A little more than a week ago I wrote about an issue about an interference
> between the way javax.activation is installed on Karaf 4.2.3 for Java 8, and
> the Javamail and the saaj-impl 1.3.1 bundles and the way they expose MIME
> handlers, which resulted in a ClassCastException. In the meantime
> Jean-Baptiste has released a new servicemix wrapper for saaj-impl 1.4.0
> (1.4.0_2), and with this bundles the ClassCastException goes away (many
> thanks for that!).
>
> I have created some test coding for the issue:
>
> A:
> Session session = Session.getInstance(System.getProperties());
> MimeMessage message = new MimeMessage(session);
> message.setSubject("Testing Subject");
> message.addHeader("X-Test-Header", "test value");
> MimeMultipart mp = new MimeMultipart("mixed");
> BodyPart part = new MimeBodyPart();
> part.setText("Test body");
> mp.addBodyPart(part);
> message.setContent(mp);
> message.saveChanges();
> ByteArrayOutputStream bos = new ByteArrayOutputStream();
> message.writeTo(bos);
>
> B:
> MessageFactory messageFactory = MessageFactory.newInstance();
> SOAPMessage message = messageFactory.createMessage();
> AttachmentPart attachmentPart = message.createAttachmentPart();
> attachmentPart.setContentId("contentid");
>
> On the first glance this seems to work now, I can invoke coding A and coding
> B in arbitrary order. However, as soon as I have another bundle in the stack
> that contains a mailcap file and is installed after the javamail bundle, code
> A will start to fail again after B was invoked. (It will work fine before
> that). The new error is now that there is no MIME handler registered for
> text/plain
>
> I think the root cause for the issue is in the OsgiMailcapCommandMap class.
>
> If a bundle contains a mailcap file, the extender from the
> org.apache.servicemix.specs.activation-api-1.1 bundle will call the
> addMailcap(String line, Bundle bundle) method, which will set the
> currentBundle attribute and then call addMailcap(String line) from the
> superclass. Eventually the addCommand() method will be called, which will add
> the current bundle to the bundles map (with the command as the key). Later in
> the createDataContentHandler() method this map will be used to look up the
> bundle and MIME handler is instantiated from the bundle classloader of that
> bundle.
>
> This works fine for all MIME handler registered via mailcap file.
> Unfortunately, the constructor of
> com.sun.xml.messaging.saaj.soap.AttachmentPartImpl (which is called by the
> message.createAttachmentPart() call) will just call the addMailcap(String
> line) method on the default command map, so the currentBundle attribute is
> not updated and the MIME handlers are registered with the last bundle that
> registered a MIME handler from a mailcap file. In the first case this is
> javamail. This even works because the javamail bundle has a
> "DynamicImport-Package: *" in it's Manifest, so the javamail classloader is
> actually able to load the MIME handlers from saaj-impl.
>
> The dirty workaround for this is to add the DynamicImport-Package: * manifest
> header to all bundles with a mailcap file, but eventually I think the
> org.apache.servicemix.specs.activation-api-1.1 should be fixed.
>
> The first solution that comes into my mind would be the following:
>
> 1. change the addMailcap(String line, Bundle bundle) method of
> OsgiMailcapCommandMap in a way that it sets currentBundle to null after
> calling the addMailcap(line) method. This way the addCommand() method will
> not add anything to the bundles map for it.
> 2. Add the DynamicImport-Package: * header to the bundle manifest file.
> This will allow OsgiMailcapCommandMap to load all Mime handler without
> registered bundle which point to exported classes with its own ClassLoader.
> 3. change the createDataContentHandler(String mimeType) to try to load the
> MIME Handler with its own class loader if no bundle is found before trying
> the ThreadContextClassloader.
>
> Alternatively one might try to find out the bundle somehow in the
> addCommand() method, but I have no good idea how to do that.
>
> What do you think?
>
> Best regards
> Stephan
>
--
Jean-Baptiste Onofré
[email protected]
http://blog.nanthrax.net
Talend - http://www.talend.com