Ausgabe
Ich habe eine eigenständige Bibliothek (JAR-Datei), die dem Klassenpfad des Anwendungsservers hinzugefügt wird, um alle laufenden Anwendungen in der JVM zu überwachen und E-Mails zu senden, wenn ein Problem auftritt.
Die JAR-Datei enthält alle Abhängigkeiten, die in der JAR-Datei gebündelt sind (unter Verwendung des Maven-Shade-Plug-ins), einschließlich der Javamail-JAR-Datei.
Wenn eine der anderen Webanwendungen auf dem Anwendungsserver Javamail als Abhängigkeit hat, tritt ein Abhängigkeitskonflikt mit Javamail in meiner JAR-Datei auf und ich erhalte eine Ausnahme
MessagingException :javax.mail.NoSuchProviderException: No provider for smtp
Wie kann ich diesen Konflikt lösen, wenn ich weiß, dass ich die laufenden Anwendungen nicht ändern kann? Ich habe nur die Kontrolle über meine JAR-Datei.
Bearbeiten :
Ich habe über die Javamail-API debuggt. und ich habe herausgefunden, dass javax.mail.Session ein neues Objekt vom Typ com.sun.mail.smtp.SMTPTransport mithilfe von Reflektion erstellt und zwei Parameter an den Konstruktor übergibt, aber anstatt SMTPTransport zu verwenden, das sich in derselben JAR-Datei befindet, die es versucht Verwenden Sie SMTPTransport aus der anderen mail.jar-Datei, die sich in einer der bereitgestellten Apps befindet.
Lösung
In Tomcat 7 suchen Webanwendungen standardmäßig zuerst nach Klassen in dieser Reihenfolge:
- zuerst auf WEB-INF/classes
- dann in den Gläsern in WEB-INF/lib
- und wenn die Klasse nicht gefunden wurde nur dann in YOUR_SERVER_HOME/lib
- Dann auf den System-Classloadern, wie hier beschrieben
Klassenversionen aus anderen WARs (auf Klassen / WEB-INF/lib) können nicht aus einem anderen WAR heraus sichtbar sein.
Können Sie uns weitere Informationen mitteilen, die uns helfen könnten, das Problem aufzuspüren:
-
Was macht die eigenständige Bibliothek im Detail, wie überwacht sie die anderen Anwendungen?
-
Wie wird die Standalone-Bibliothek zum Server-Klassenpfad hinzugefügt? Wird es auf YOUR_SERVER_HOME/lib kopiert oder ist es ein Ordner, der dem Serverklassenpfad über die Eigenschaften shared.loader oder common.loader von catalina.properties hinzugefügt wird
-
stellt jede WAR-Anwendung ihre eigenen Mail-Jars auf WEB-INF/lib bereit oder wird die Bibliothek auf Serverebene als JNDI-Ressource veröffentlicht, wie hier im Abschnitt Installieren der JavaMail-Bibliotheken erwähnt
-
Läuft eine der Anwendungen auf dem Server NICHT im oben erwähnten Standard-Classloading-Modus und verwendet “delegate = true” (was bedeutet, dass sie zuerst auf dem Server und erst dann auf dem WAR nachsieht)? Hier ist, wie dies konfiguriert werden würde, suchen Sie nach einem Resource-Element in der context.xml oder server.xml
Einige Vorschläge für mögliche Lösungen:
-
Installieren Sie JavaMail auf Tomcat 7 als JNDI-Ressource gemäß den Installationsanweisungen hier im Abschnitt Installieren Sie die JavaMail-Bibliotheken . Lassen Sie alle Anwendungen die JNDI-Ressource wie in der Tomcat-Dokumentation verwenden und entfernen Sie Java-Mail aus der eigenständigen Bibliothek, indem Sie einen Shade-Plug-in-Ausschluss verwenden. Dies wird immer funktionieren und ist die am meisten empfohlene Lösung.
-
Wenn Sie Java 7 verwenden, versuchen Sie, JHades zu verwenden, um den Klassenpfad der verschiedenen Anwendungen zu beheben. Sie können eine statische Analyse der WARs für doppelte Klassen durchführen oder anzeigen, welche Versionen zur Laufzeit einer bestimmten Klasse verwendet werden und welche anderen Versionen verfügbar sind.
-
Da es keine Kontrolle über die Bereitstellungseinstellungen der anderen Anwendungen oder deren Inhalt, die Verwendung von JNDI usw. gibt, besteht eine Lösung, die sicher in allen Umgebungen und mit jeder Anwendung funktioniert, darin, das Tool so umzugestalten, dass es keine Mail benötigt .jar auf dem Server installiert werden. Das Tool kann eine E-Mail-Anfrage beispielsweise in eine Datei oder eine Datenbanktabelle schreiben, und eine andere auf dem Server bereitgestellte WAR-Datei würde die Tabellendatei abfragen und die E-Mail senden. Oder es wird ein Bash/Bat-Skript aufgerufen, das die E-Mail selbst auf einem separaten Java-Prozess versendet.
Leistungsanalysetools wie Dynatrace basieren auf JVM-Agenten und verwenden einen ähnlichen Mechanismus, der keine Einführung von Bibliotheken auf Serverebene erfordert, der Agent sammelt Daten und sendet sie an einen Sammelprozess, der sie irgendwo für weitere Analysen speichert, z B. Alarme per E-Mail versenden usw.
Ich hoffe, das hilft, im Allgemeinen sehe ich keine Möglichkeit, Bibliotheken auf einem EE-Server bereitzustellen und sicher zu sein, dass sie niemals Probleme für Anwendungen auf verschiedenen Servertypen und verschiedenen Einstellungen für das Laden von Anwendungsklassen verursachen.
Das Beste ist wahrscheinlich, das Tool so anzupassen, dass es auf ein Minimum an Bibliotheken angewiesen ist, die auf dem Server bereitgestellt werden, indem es in separate Module aufgeteilt wird, wobei nur das Sammelmodul auf dem Server ausgeführt wird, oder nach Alternativen wie Dynatrace suchen.
Beantwortet von – Angular University
Antwort geprüft von – Dawn Plyler (FixError Volunteer)