karaf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Siano, Stephan" <stephan.si...@sap.com>
Subject News from the karaf 4.2.3/activation/saaj-impl/javamail issue on Java 8
Date Mon, 11 Feb 2019 11:35:52 GMT
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

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message