2 votes

Pourquoi JAR fonctionne correctement lorsqu'il est placé à l'intérieur des bibliothèques WAR mais pas à l'intérieur des bibliothèques partagées de Tomcat?

J'ai une application (WAR) déployée sur Tomcat, contenant plusieurs fichiers jar. Pour des raisons, j'ai besoin de prolonger une classe à l'intérieur de l'un de ces fichiers jar et de substituer l'une de ses méthodes. La nouvelle méthode sera différente pour chaque client en fonction de leurs besoins.

Ce que j'ai fait est de créer un petit fichier jar qui dépend du jar principal, d'ajouter la classe qui étend celle d'origine, et de le compiler.

Maintenant, je veux le déployer sur Tomcat afin que la nouvelle classe soit chargée par Spring. Cela fonctionne bien si je mets le nouveau jar à l'intérieur de WEB-INF/lib du WAR déployé, mais cela ne fonctionne pas si je le mets à l'intérieur de shared/lib (ou simplement lib) de Tomcat. L'erreur est ClassNotFoundException pour celui que j'étends (en gros, chaque classe provenant du jar principal ne peut pas être trouvée). J'ai déjà vérifié catalina.properties et il charge correctement le .jar dans les deux emplacements.

Ma question est : pourquoi ce JAR ne fonctionne que si je le mets à l'intérieur des bibliothèques du WAR mais pas si je le mets à l'intérieur de la bibliothèque partagée de Tomcat ? La version de Tomcat est la 7.0.86

Un petit schéma pour donner une meilleure idée de ce qui fonctionne et de ce qui ne fonctionne pas :

    - dossier tomcat
      - lib
        - jar-qui-étend-le-jar-principal.jar (ClassNotFoundException pour celui que j'étends)
      - shared
        - lib
          - jar-qui-étend-le-jar-principal.jar (ClassNotFoundException pour celui que j'étends)
      - webapps
        - my-application
          - WEB/INF
            - lib
              - jar-qui-étend-le-jar-principal.jar (cela fonctionne correctement et je peux utiliser ma classe personnalisée)

4voto

dunni Points 8810

Tomcat utilise différents ClassLoaders dans une sorte de hiérarchie arborescente (vous pouvez voir une image ainsi que quelques explications ici: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html).

Fondamentalement, vous avez un Classloader par application Web, un pour les bibliothèques partagées, un pour le système et un pour le démarrage, où les classloaders de l'application Web sont en bas de l'arborescence, puis cela monte. Cependant, un Classloader ne peut accéder qu'à ses classloaders parent, mais pas dans l'autre sens, donc lorsqu'il recherche une classe, un Classloader vérifiera d'abord ses propres classes, puis demandera à ses classloaders parent pour cette classe spécifique.

C'est pourquoi vous pouvez accéder aux classes dans le classloader partagé depuis votre application Web, mais pas dans l'autre sens.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X