multiple versions of javamail jar causing NoSuchProviderException

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-24 17:04:28

问题


I have a standalone library ( jar file) that is added to the application server classpath to monitor all the running applications in the JVM and send email when some issue happens.

the jar file have all the dependencies bundled in the jar (using the maven-shade-plugin) including the javamail jar file.

When one of the other webapplications in the appserver have javamail as a dependency, some dependency conflict happens with the javamail in my jar file and I get an exception

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

How can I solve this conflict knowing that I can't modify the running appplications. I only have control over my jar file.

Edit:

I debugged through the javamail API. and I found out that the javax.mail.Session construct a new object of type com.sun.mail.smtp.SMTPTransport using reflection and pass two parameters to the constructor, but rather than using SMTPTransport located in the same jar file it tries to use SMTPTransport from the other mail.jar located in one of the deployed apps.


回答1:


In tomcat 7, by default web applications will look first for classes on this order:

  1. first on WEB-INF/classes
  2. then inside jars in WEB-INF/lib
  3. and if the class was not found only then in YOUR_SERVER_HOME/lib
  4. Then on the system classloaders, as described here

Class versions from other WARs (on classes / WEB-INF/lib) cannot be visible from inside another WAR.

Can you let us know of further info that could help track down the problem:

  • what does the standalone library do in more detail, how does it monitor the other applications?

  • how is the standalone library added to the server classpath? Is it copied on YOUR_SERVER_HOME/lib, or is a folder added to the server classpath via shared.loader or common.loader properties of catalina.properties

  • does each WAR application provide it's own mail jars on WEB-INF/lib, or is the library published at the server level as a JNDI resource such as mentioned here on section Install the JavaMail libraries

  • Is any of the applications in the server NOT running in the default classloading mode that I mentioned above, and is using delegate = true (meaning it will look on the server first and only then on the WAR) ? here is how this would be configured, check for a Resource element in the context.xml or server.xml

Some suggestions for possible solutions:

  1. Install JavaMail on tomcat 7 as a JNDI resource following the installation instructions here on section Install the JavaMail libraries. Have all applications use the JNDI resource as in the tomcat docs, and remove java mail from the standalone library using a shade plugin exclusion. This will always work and it's the most recommended solution.

  2. If you are using Java 7, try to use JHades to troubleshoot the classpath of the different applications. You can do static analysis on the WARs for duplicate classes, or view what are the versions used at runtime of a given class, and which other versions are available.

  3. Since there is no control over the deployment settings of the other applications or their contents, use of JNDI, etc., a solution that will work for sure in all environments and with any application is to refactor the tool so that it does not require mail.jar to be installed on the server. The tool can write an email request to for example a file or a database table, and another WAR deployed on the server would poll the table file and send the mail. Or a bash/bat script is called that itself sends the email on a separate java process.

Performance analysis tools such as Dynatrace are based on JVM agents and use a similar mechanism that does not need the introduction of libraries at the server level, the agent collects data and sends it to a collecting process that stores it somewhere for further analisys, treatment such as send alarms via emails, etc.

Hope this helps, in general I don't see any way to deploy libraries to a EE server and be sure that they will never cause problems to any application on different server types and different application classloading settings.

The best is probably adapt the tool so that it relies on a minimum of libraries deployed on the server, breaking it up into separate modules with only the collecting module running on the server or look into alternatives such as Dynatrace.




回答2:


I'm not familiar with the maven-shade-plugin. Does it package the original jar files in a new jar file? Does it extract the contents of the original jar files and insert the contents into the new jar file? If the latter, it may only be including the class files and not the resource files in META-INF that configure the JavaMail providers.

Of course, the best approach would be to arrange for only one copy of the JavaMail jar file to be included in the server's classpath.




回答3:


Upgrade the JavaMail version included with Tomcat 7 to JavaMail to 1.5.3 which contains the fix for Bug 6668 -skip unusable Store and Transport classes. You can download the latest snapshot and official releases from the JavaMail reference implementation home page.



来源:https://stackoverflow.com/questions/19778327/multiple-versions-of-javamail-jar-causing-nosuchproviderexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!