javamail jar的多个版本导致NoSochProviderException

javamail jar的多个版本导致NoSochProviderException,java,classpath,classloader,jakarta-mail,Java,Classpath,Classloader,Jakarta Mail,我有一个独立的库(jar文件),它被添加到应用程序服务器类路径中,用于监视JVM中所有正在运行的应用程序,并在出现问题时发送电子邮件 jar文件将所有依赖项捆绑在jar中(使用maven shade插件),包括javamail jar文件 当appserver中的另一个Web应用程序将javamail作为依赖项时,jar文件中的javamail会发生一些依赖项冲突,我会得到一个异常 MessagingException :javax.mail.NoSuchProviderException: N

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

jar文件将所有依赖项捆绑在jar中(使用maven shade插件),包括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.transport类型的新对象,并将两个参数传递给构造函数,但是它没有使用位于同一jar文件中的SMTPTransport,而是尝试使用位于其中一个已部署应用程序中的另一个mail.jar中的SMTPTransport。

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


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

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

  • 首先介绍WEB-INF/Class
  • 然后在WEB-INF/lib中的JAR中
  • 如果没有找到该类,则只能在您的\u服务器\u HOME/lib中找到
  • 然后在系统类装入器上,如所述
  • 其他WAR中的类版本(在Class/WEB-INF/lib上)无法从另一个WAR中看到

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

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

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

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

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

    关于可能的解决办法的一些建议:

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

  • 如果您使用的是Java7,请尝试使用来解决不同应用程序的类路径问题。您可以对重复类的WAR进行静态分析,或者查看给定类在运行时使用的版本以及其他可用版本

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

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

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


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

    将Tomcat 7附带的JavaMail版本升级为1.5.3,其中包含针对的修复程序。您可以从主页下载最新的快照和官方版本。

    shade插件将内容提取到原始jar中,并提取meta inf文件。很遗憾,我不知道服务器上现有的应用程序是否可以安排1个副本。您使用的是哪台服务器?JavaEE应用服务器将包含JavaMail,因此web应用程序或您的应用程序不需要包含它。我认为它不包括javamail jar文件的副本。谢谢你的建议。我只是以Tomcat为例,因为它是我正在开发的应用服务器。但该解决方案应该可以跨其他应用服务器移植。回答你的问题。1) 独立库是一个库,它通过AOP监控web应用程序的性能,并在某些方法执行时间较慢时向用户发出警报