eclipse-ee4j / angus-mail

Angus Mail
https://eclipse-ee4j.github.io/angus-mail
Other
58 stars 16 forks source link

MailcapCommandMap can not load Mime Handlers in OSGI Runtime #148

Open precoder opened 6 months ago

precoder commented 6 months ago

Hello,

We are trying to move from Javax to Jakarta dependencies in OSGI but we can not find a set of runtime dependencies for the Jakarta Mail and Jakarta Activation.

I have following JARs in the OSGI Runtime: jakarta.activation:jakarta.mail-api.jar (version 2.1.2) org.eclipse.angus:jakarta.mail.jar (version 2.0.3) jakarta.activation:jakarta.activation-api.jar (version 2.1.3) org.eclipse.angus:angus-activation.jar (version 2.0.2)

We get following error as we try to send an Email in MailcapCommandMap: Can't load DCH org.eclipse.angus.mail.handlers.multipart_mixed; Exception: java.lang.ClassNotFoundException: org.eclipse.angus.mail.handlers.multipart_mixed not found by jakarta.activation-api [39]

How should the MailcapCommandMap find the correct class Loader for the "multipart_mixed" handler?

cld = SecuritySupport.getContextClassLoader(); -> loads the application class loader and it does not contain multipart_mixed handlers. cld = this.getClass().getClassLoader(); -> loads the bundle class loader for jakarta.activation-api als does not contain multipart_mixed handlers. cl = Class.forName(name); -> same class loader as this.getClass().getClassLoader().

None of the above loaded the handlers correctly. Our current idea is putting all JARs from above into a single bundle as dependencies and export everyting from the same bundle which is sharing the same class loader as a workaround solution.

How should it be working in the OSGI runtime?

jbescos commented 6 months ago

Could you try with this one?: https://mvnrepository.com/artifact/org.eclipse.angus/jakarta.mail/2.0.3

And also remove jakarta.mail-api.jar. This is included inside org.eclipse.angus:jakarta.mail, so there is no need to have it twice.

jmehrens commented 6 months ago

There is also: https://github.com/jakartaee/jaf-api/issues/161. There is useful information there.

I'm not finished with that PR but, I think Mail will have to add entries to CommandMap on set or we need to modify the streamprovider interface to generate commandmap.

precoder commented 5 months ago

I put all 3 dependencies (2 Jakarta Activation and 1 Angus Jakarta Mail, that contains API and Impl) into same bundle in embedded mode and activated the Debug Logs for Activation and Mail: file:osgiBundles/de.test.bundle.product.mail.adapter.jar \ Here is the output on the Gogo Shell:

g! MailcapCommandMap: load HOME
MailcapRegistry: can't load from file - C:\Users\user\.mailcap; Exception: java.io.FileNotFoundException: C:\Users\user\.mailcap (The system cannot find the file specified)
MailcapCommandMap: load SYS
MailcapRegistry: can't load from file - C:\test\work\programs\java\jdk-17.0.8.1+1\conf\mailcap; Exception: java.io.FileNotFoundException: C:\test\work\programs\java\jdk-17.0.8.1+1\conf\mailcap (The system cannot find the file specified)
MailcapCommandMap: load JAR
MailcapCommandMap: !anyLoaded
MailcapCommandMap: successfully loaded mailcap file: /META-INF/mailcap
MailcapCommandMap: load DEF
MailcapCommandMap: successfully loaded mailcap file: /META-INF/mailcap.default
MailcapCommandMap: createDataContentHandler for multipart/mixed
  search DB #1
  search DB #2
  search fallback DB #1
    got content-handler
      class org.eclipse.angus.mail.handlers.multipart_mixed
May 22, 2024 1:16:31 PM jakarta.mail.Session loadResource
WARNING: expected resource not found: /META-INF/javamail.default.address.map
MimetypesFileTypeMap: load HOME
MimeTypeRegistry: can't load from file - C:\Users\user\.mime.types; Exception: java.io.FileNotFoundException: C:\Users\user\.mime.types (The system cannot find the file specified)
MimetypesFileTypeMap: load SYS
MimeTypeRegistry: can't load from file - C:\test\work\programs\java\jdk-17.0.8.1+1\conf\mime.types; Exception: java.io.FileNotFoundException: C:\test\work\programs\java\jdk-17.0.8.1+1\conf\mime.types (The system cannot find the file specified)
MimetypesFileTypeMap: load JAR
MimetypesFileTypeMap: !anyLoaded
MimetypesFileTypeMap: not loading mime types file: /META-INF/mime.types
MimetypesFileTypeMap: load DEF
MimetypesFileTypeMap: successfully loaded mime types file: /META-INF/mimetypes.default
MailcapCommandMap: createDataContentHandler for multipart/mixed
  search DB #1
  search DB #2
  search fallback DB #1
    got content-handler
      class org.eclipse.angus.mail.handlers.multipart_mixed
MailcapCommandMap: createDataContentHandler for text/plain
  search DB #1
    got content-handler
      class org.eclipse.angus.mail.handlers.text_plain

It works as expected. I first send a mail and recieve the same Email. Here If I put all 3 bundles alone on the runtime, Mail Cap can not find MIME Parsers:

g!
May 22, 2024 1:21:59 PM jakarta.mail.Session loadResource
WARNING: expected resource not found: /META-INF/javamail.default.address.map
MimetypesFileTypeMap: load HOME
MimeTypeRegistry: can't load from file - C:\Users\user\.mime.types; Exception: java.io.FileNotFoundException: C:\Users\user\.mime.types (The system cannot find the file specified)
MimetypesFileTypeMap: load SYS
MimeTypeRegistry: can't load from file - C:\test\work\programs\java\jdk-17.0.8.1+1\conf\mime.types; Exception: java.io.FileNotFoundException: C:\test\work\programs\java\jdk-17.0.8.1+1\conf\mime.types (The system cannot find the file specified)
MimetypesFileTypeMap: load JAR
MimetypesFileTypeMap: !anyLoaded
MimetypesFileTypeMap: not loading mime types file: /META-INF/mime.types
MimetypesFileTypeMap: load DEF
MimetypesFileTypeMap: successfully loaded mime types file: /META-INF/mimetypes.default
MailcapCommandMap: load HOME
MailcapRegistry: can't load from file - C:\Users\user\.mailcap; Exception: java.io.FileNotFoundException: C:\Users\user\.mailcap (The system cannot find the file specified)
MailcapCommandMap: load SYS
MailcapRegistry: can't load from file - C:\test\work\programs\java\jdk-17.0.8.1+1\conf\mailcap; Exception: java.io.FileNotFoundException: C:\test\work\programs\java\jdk-17.0.8.1+1\conf\mailcap (The system cannot find the file specified)
MailcapCommandMap: load JAR
MailcapCommandMap: !anyLoaded
MailcapCommandMap: not loading mailcap file: /META-INF/mailcap
MailcapCommandMap: load DEF
MailcapCommandMap: successfully loaded mailcap file: /META-INF/mailcap.default
MailcapCommandMap: createDataContentHandler for multipart/mixed
  search DB #1
  search fallback DB #1

g! MailcapCommandMap: createDataContentHandler for multipart/mixed
  search DB #1
  search fallback DB #1  

On the Felix Runtime I have:

file:osgiBundles/jakarta.activation-api.jar \
file:osgiBundles/angus-activation.jar \
file:osgiBundles/jakarta.mail.jar \

37|Active     |    3|Jakarta Activation API (2.1.3)|2.1.3
38|Active     |    3|Angus Activation Registries (2.0.2)|2.0.2
39|Active     |    3|Angus Mail default provider (2.0.3)|2.0.3

Here are the maven dependencies I used, they are the latest in the Maven as I tried:

<dependency>
    <groupId>org.eclipse.angus</groupId>
    <artifactId>jakarta.mail</artifactId>
    <version>2.0.3</version>
</dependency>
<dependency>
    <groupId>jakarta.activation</groupId>
    <artifactId>jakarta.activation-api</artifactId>
    <version>2.1.3</version>
</dependency>
<dependency>
    <groupId>org.eclipse.angus</groupId>
    <artifactId>angus-activation</artifactId>
    <version>2.0.2</version>
</dependency>

For now I have a solution as above since embedding all 3 into another Bundle works as expected.

chrisrueger commented 4 days ago

Our current idea is putting all JARs from above into a single bundle as dependencies and export everyting from the same bundle which is sharing the same class loader as a workaround solution.

We have done the same and wrapped all relevant jars via bnd / bndtools into a single OSGi bundle, so that all those bundles share the same bundle-classloader which can see all relevant classes of all jar files.

For those interested here is a bnd file which does that:

-resourceonly: true

Bundle-Version: 2.1.3

Export-Package: \
    *; -split-package:=merge-first

Import-Package: \
    org.graalvm.nativeimage.hosted;resolution:=optional,\
    sun.security.util;resolution:=optional,\
    *

-includeresource: \
    ${repo;jakarta.activation:jakarta.activation-api;latest}; lib:=true,\
    ${repo;org.eclipse.angus:angus-activation;latest}; lib:=true,\
    ${repo;jakarta.mail:jakarta.mail-api;latest}; lib:=true,\
    ${repo;org.eclipse.angus:angus-mail;latest}; lib:=true,\
    @${repo;org.eclipse.angus:angus-mail;latest}!/META-INF/*,\
    @${repo;jakarta.activation:jakarta.activation-api;latest}!/META-INF/*,\
    @${repo;org.eclipse.angus:angus-mail;latest}!/META-INF/javamail.default.providers;rename:=META-INF/javamail.providers

-buildpath: \
    ${repo;jakarta.activation:jakarta.activation-api;latest},\
    ${repo;org.eclipse.angus:angus-activation;latest},\
    ${repo;jakarta.mail:jakarta.mail-api;latest},\
    ${repo;org.eclipse.angus:angus-mail;latest},\

Note: rename:=META-INF/javamail.providers is a hack to get the content of META-INF/javamail.default.providers into javamail.providers, because unfortunately another classloading issue (I think related to StreamProviders https://github.com/jakartaee/jaf-api/issues/161 ) did not load META-INF/javamail.default.providers but only META-INF/javamail.providers

helpful: -includeresource and wrapping libraries