osgi - 将 JavaMail 1.5 与 XPage 结合使用

标签 osgi xpages jakarta-mail

我有一个 XPage 应用程序应该通过 IMAP(和 SSL)从 GMail 读取邮件并将它们存储在 nsf 数据库中。

为此,我需要 JavaMail 1.5。

在阅读了一些帖子后,我得出的结论是我必须构建自己的 OSGI 插件。 在 http://www.dalsgaard-data.eu/blog/wrap-an-existing-jar-file-into-a-plug-in/ 上关注 John Dalsgaard 的博客我能够将 JavaMail 1.5 jar 文件包装到 OSGI 插件中。该插件导出所有 JavaMail 包,以便我可以在我的 XPage 应用程序中使用它们。

在我的 XPage 中有一些 java 代码试图建立与 GMail 的连接。但是连接总是超时,所以我打开了javamail的调试选项。调试显示我的 java 代码仍然使用 javamail 1.3(由 domino 服务器提供的版本)。

因此,我将我的 java 代码移到了 OSGI-Plugin 中并导出了包,这样我仍然可以在我的 XPage 中使用它。为 javamail 打开调试显示正确的版本 1.5。但是现在无论我使用 imap 还是 imaps 作为协议(protocol),我都会得到异常 javax.mail.NoSuchProviderException

我错过了什么?为什么我不能在 osgi-plugin 中使用 javamail 1.5 jar 文件?

最佳答案

javax.mail 的代码并不是真正的 OSGi 友好。它使用线程上下文 ClassLoader 来查找实例化实现。

你可以通过以下方式来欺骗它:

  • 将 javax.mail 和 com.sun.mail.imap 安装到您的 OSGi 容器中。版本 1.5.2 具有 OSGi list header ,因此它应该可以工作
  • 当您调用加载 Provider 的 javax.mail api 函数时,将线程上下文类加载器设置为确定知道 imap 类的类加载器。

例如:

Thread thread = Thread.currentThread();
ClassLoader previousCl = thread.getContextClassLoader();
thread.setContextClassLoader(IMAPStore.class.getClassLoader());
try {
    session.getStore("imaps");
} finally {
    thread.setContextClassLoader(previousCl);
}

请注意,我还没有对此进行测试,但解决方案应该看起来很相似。您可能需要将更多 javax.mail 命令放入 try block 中(例如获取 session )。

不那么丑陋的解决方案

一个不太难看的解决方案是,如果您跳过 javax.mail API 的使用并直接使用 imap 的类。

例如:

Session session = Session.getDefaultInstance(...);
Store imapStore = new IMAPStore(session, url);

在 Java EE 中使用 SPI 或类似解决方案时,通常可以通过跳过工厂机制(使用线程上下文类加载器和其他技巧)并直接实例化实现类来实现相同的功能。

更新

在命令中声明有一个异常(exception):

com.sun.mail.handlers.multipart_mixed incompatible with javax.activation.DataContentHandler

原因似乎是 javax.activation.* 包在 OSGi 容器中可用了两次。它来自 JDK,也来自其中一个 bundle 。问题类似here原因也来自重复的包。

然而,真正的原因是再次使用了Thread Context ClassLoader。如果查看引发异常的源代码,您将看到线程上下文类加载器用于加载类。这是一个问题,因为我猜 TCC 是系统类加载器,而 javax.mail 连接到 javax.activation 包。

我现在可以想象以下选项:

  • 删除 javax.activation 包。这可能会解决问题,因为在这种情况下,每个包都将连接到系统包。但是,您以后仍然可以获得 ClassNotFoundExceptions ......与类加载器的不良做法作斗争:)。
  • 从系统包中删除 javax.activation。在那种情况下,每个人都将连接到 bundle 。然而,同样的问题可能会发生,即 javax.activation 包(或 TCC)看不到应该加载的类。
  • 在堆栈跟踪中找到一个点,您可以在其中更改 TCC 并设置一个可以查看所有必要类的类加载器。这又是单体技术的常用技巧(就像在原始示例中一样,但现在用于此函数调用)。
  • 找到一种具有这些功能但对 OSGi 更友好的技术。如果你能找到一个,请张贴在这里:)。

关于osgi - 将 JavaMail 1.5 与 XPage 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26912985/

相关文章:

java - 使用 pax-maven-plugin 构建时将我自己的包源添加到 pax-exam

xpages - 在 SSJS 中执行操作的服务器日期和时间

javascript - 尝试在 XPage 上使用 'executeOnServer' 从 Javascript 触发 SSJS

java - 如何使用 javamail 从 .eml 文件读取多封电子邮件

java - 如何使用 Apache Camel + SSL 接收电子邮件?

java - osgi r6 service.component.annotations 属性列表

java - 在 Apache Servicemix 4 中的 OSGi 包之间共享配置文件?

spring - 从 BundleContextAware 类访问应用程序上下文

xpages - IBM Domino XPage 的双因素身份验证

java - javamail Authenticator 的构造函数如何工作?