多个版本的javamail jar导致NoSuchProviderException

时间:2013-11-04 22:17:39

标签: java classpath classloader javamail

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

jar文件包含jar中的所有依赖项(使用maven-shade-plugin),包括javamail jar文件。

当appserver中的其他一个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。

3 个答案:

答案 0 :(得分:3)

在tomcat 7中,默认情况下 Web应用程序将首先查看此订单上的类:

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

    其他WAR中的类版本(在类/ WEB-INF / lib上)在另一个WAR内部无法显示。

    您能告诉我们有助于追踪问题的更多信息:

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

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

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

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

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

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

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

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

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

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

      最好的可能是调整工具,使其依赖于服务器上部署的最少的库,将其分解为单独的模块,只在服务器上运行收集模块或查看Dynatrace等替代方案。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

将Tomcat 7附带的JavaMail版本升级到JavaMail到1.5.3,其中包含Bug 6668 -skip unusable Store and Transport classes的修复程序。您可以从JavaMail reference implementation主页下载最新的快照和正式版本。

相关问题