1

我有一个独立的库(jar 文件),它被添加到应用程序服务器类路径中,以监视 JVM 中所有正在运行的应用程序,并在发生某些问题时发送电子邮件。

jar 文件将所有依赖项捆绑在 jar 中(使用 maven-shade-plugin),包括 javamail jar 文件。

当应用服务器中的其他 Web 应用程序之一将 javamail 作为依赖项时,我的 jar 文件中的 javamail 会发生一些依赖项冲突,并且出现异常

MessagingException :javax.mail.NoSuchProviderException: No provider for smtp 

知道我无法修改正在运行的应用程序,我该如何解决这个冲突。我只能控制我的 jar 文件。

编辑

我通过 javamail API 进行了调试。我发现 javax.mail.Session 使用反射构造了一个 com.sun.mail.smtp.SMTPTransport 类型的新对象并将两个参数传递给构造函数,而不是使用位于它尝试的同一个 jar 文件中的 SMTPTransport使用位于已部署应用程序之一中的另一个 mail.jar 的 SMTPTransport。

4

3 回答 3

3

在 tomcat 7 中,默认情况下, Web 应用程序将首先按以下顺序查找类:

  1. 首先是 WEB-INF/classes
  2. 然后在 WEB-INF/lib 的 jars 中
  3. 如果仅在 YOUR_SERVER_HOME/lib 中找不到该类
  4. 然后在系统类加载器上,如此处所述

来自其他 WAR 的类版本(在类/WEB-INF/lib 上)不能从另一个 WAR 中看到。

您能否让我们知道有助于追查问题的更多信息:

  • 独立库更详细地做了什么,它如何监控其他应用程序?

  • 独立库如何添加到服务器类路径中?它是在 YOUR_SERVER_HOME/lib 上复制的,还是通过 catalina.properties 的 shared.loader 或 common.loader 属性添加到服务器类路径的文件夹

  • 每个 WAR 应用程序是否在 WEB-INF/lib 上提供它自己的邮件 jar,或者是在服务器级别作为 JNDI 资源发布的库,例如在安装 JavaMail 库部分中提到

  • 服务器中的任何应用程序是否没有在我上面提到的默认类加载模式下运行,并且正在使用 delegate = true (意味着它会先在服务器上查看,然后才在 WAR 上查看)?是如何配置的,检查 context.xml 或 server.xml 中的 Resource 元素

一些可能的解决方案的建议:

  1. 按照安装 JavaMail 库部分的安装说明在 tomcat 7 上安装 JavaMail 作为 JNDI 资源。让所有应用程序像在 tomcat 文档中一样使用 JNDI 资源,并使用 shade 插件排除从独立库中删除 java 邮件。这将始终有效,这是最推荐的解决方案。

  2. 如果您使用的是 Java 7,请尝试使用JHades对不同应用程序的类路径进行故障排除。您可以对重复类的 WAR 进行静态分析,或者查看给定类在运行时使用的版本以及可用的其他版本。

  3. 由于无法控制其他应用程序的部署设置或其内容、JNDI 的使用等,因此在所有环境和任何应用程序中都可以肯定工作的解决方案是重构该工具,使其不需要邮件.jar 要安装在服务器上。该工具可以将电子邮件请求写入例如文件或数据库表,并且部署在服务器上的另一个 WAR 将轮询表文件并发送邮件。或者调用一个 bash/bat 脚本,它本身在一个单独的 java 进程上发送电子邮件。

Dynatrace 等性能分析工具基于 JVM 代理,使用类似的机制,不需要在服务器级别引入库,代理收集数据并将其发送到收集进程,该进程将其存储在某处以供进一步分析,处理此类如通过电子邮件发送警报等。

希望这会有所帮助,一般来说,我看不到将库部署到 EE 服务器的任何方法,并确保它们永远不会对不同服务器类型和不同应用程序类加载设置上的任何应用程序造成问题。

最好的方法可能是调整该工具,使其依赖于部署在服务器上的最少库,将其分解为单独的模块,仅在服务器上运行收集模块,或者寻找替代方案,例如 Dynatrace。

于 2013-11-07T00:31:22.457 回答
0

我不熟悉 maven-shade-plugin。它是否将原始 jar 文件打包到一个新的 jar 文件中?它会提取原始 jar 文件的内容并将内容插入到新的 jar 文件中吗?如果是后者,它可能只包括类文件而不是 META-INF 中配置 JavaMail 提供程序的资源文件。

当然,最好的方法是只安排一份 JavaMail jar 文件的副本包含在服务器的类路径中。

于 2013-11-05T08:20:40.273 回答
0

将 Tomcat 7 中包含的 JavaMail 版本升级到 JavaMail 到 1.5.3,其中包含对错误 6668 的修复 - 跳过不可用的存储和传输类您可以从JavaMail 参考实现主页下载最新的快照和官方版本。

于 2015-01-21T17:18:46.560 回答