Comment lire le fichier manifeste d’une application Web exécutée dans apache tomcat?

J’ai une webapp contenant un fichier manifeste dans lequel j’écris la version actuelle de mon application lors d’une tâche de compilation ant. Le fichier manifeste est créé correctement, mais lorsque j’essaie de le lire pendant l’exécution, j’obtiens des effets secondaires étranges. Mon code pour lire dans le manifeste est quelque chose comme ceci:

InputStream manifestStream = Thread.currentThread() .getContextClassLoader() .getResourceAsStream("META-INFFFF/MANIFEST.MF"); try { Manifest manifest = new Manifest(manifestStream); Atsortingbutes atsortingbutes = manifest.getMainAtsortingbutes(); Ssortingng impVersion = atsortingbutes.getValue("Implementation-Version"); mVersionSsortingng = impVersion; } catch(IOException ex) { logger.warn("Error while reading version: " + ex.getMessage()); } 

Quand j’attache eclipse à tomcat, je vois que le code ci-dessus fonctionne, mais il semble avoir un fichier manifeste différent de celui auquel je m’attendais, ce que je peux dire car la version ant et le timestamp sont différents. Ensuite, je mets “META-INFFFF” et le code ci-dessus fonctionne toujours! Cela signifie que je lis un autre manifeste, pas le mien. J’ai aussi essayé

 this.getClass().getClassLoader().getResourceAsStream(...) 

Mais le résultat était le même. Quelle est la bonne façon de lire le fichier manifeste à l’intérieur d’une application Web exécutée dans tomcat?

Edit : Merci pour les suggestions jusqu’à présent. De plus, je dois noter que j’exécute tomcat autonome; Je le lance à partir de la ligne de commande, puis je l’attache à l’instance en cours d’exécution dans le débogueur d’Eclipse. Cela ne devrait pas faire la différence, n’est-ce pas?

Peut-être que vos effets secondaires viennent du fait que presque tous les bocaux contiennent un MANIFEST.MF et que vous n’obtenez pas le bon. Pour lire le MANIFEST.MF de l’application Web, je dirais:

 ServletContext application = getServletConfig().getServletContext(); InputStream inputStream = application.getResourceAsStream("/META-INF/MANIFEST.MF"); Manifest manifest = new Manifest(inputStream); 

Veuillez noter que l’exécution de Tomcat à partir d’Eclipse n’est pas identique à l’exécution de Tomcat seul lorsque Eclipse joue avec le chargeur de classes.

un peu tard, mais ça marche pour moi (appli web dans Glassfish)

 Properties prop = new Properties(); prop.load(getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF")); System.out.println("All atsortingbutes:" + prop.ssortingngPropertyNames()); System.out.println(prop.getProperty("{whatever atsortingbute you want}")); 

Essayez d’utiliser jcabi-manifestests , qui fait tout ce chargement pour vous. Par exemple:

 Ssortingng version = Manifests.read("My-Version"); 

charge l’atsortingbut My-Version partir de l’un des fichiers MANIFEST.MF disponibles.

Il est important de mentionner que (plus de détails sont ici ) dans la plupart des conteneurs Web, le chargeur de classes de threads actuel est différent du chargeur de classes de contexte de servlet. C’est pourquoi vous devez append votre contexte de servlet au registre à l’exécution ( plus d’informations ):

 Manifests.append(servletContext); 

Aussi, vérifiez ceci: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

La méthode par défaut utilisée par les chargeurs de classe consiste à s’en remettre au parent avant d’essayer de rechercher leurs propres ressources. Donc, si un chargeur de classe parent a un manifeste disponible, c’est ce que vous obtiendrez. En fait, les serveurs d’applications ne le font pas nécessairement pour permettre aux applications de remplacer les versions des bibliothèques. De plus, les chargeurs de classe peuvent avoir plusieurs jarres et donc plusieurs manifestes.

Il peut être capable d’obtenir une URL de ressource de l’une de vos ressources nommées de manière unique. Ouvrez une connexion. Cast à JarURLConnection . Obtenez le JarFile . Chargez le manifeste à partir de cela. Cela peut ne pas fonctionner, surtout si Tomcat fait exploser la guerre.

[Update] Bien sûr, le fichier war lui-même n’est pas sur le classpath. Le classpath aura quelque chose comme WEB-INF / lib / ( .jar | .zip) et WEB-INF / classes /. Obtenir une ressource à partir de ServletContext devrait fonctionner.

Meilleure solution: Faites quelque chose de différent. 🙂

Le bon manifeste existe dans la racine de l’application sur le serveur. Découvrez la racine de l’application, par exemple en recherchant classpath de votre classe:

 Ssortingng rootPath = getClass().getProtectionDomain().getCodeSource().getLocation().getPath() 

Remplacez ensuite le chemin ci-dessus par le chemin fondé: Exemple Glassfish:

 /applications//META-INF/MANIFEST.MF 

Ça marche pour moi.

Je ne sais pas à propos d’un moyen “officiel” de le lire, mais si MANIFEST.MF ne peut pas être correctement chargé en tant que ressource, que diriez-vous d’essayer de dériver son chemin à partir d’un “ServletContext.getRealPath ()” sur un chemin Web? défini dans votre application?

Ecrire la version de l’application à un autre endroit (un fichier de propriétés dans WEB-INF / classes) par ant pendant la construction est une autre solution qui me vient à l’esprit.

C’est ce que je fais pour imprimer différentes versions sur un fichier journal. J’ai codé en dur un chemin étendu mais les applications peuvent utiliser servletContext.getRealPath("/") pour lire un chemin complet vers le dossier webapp. Peut imprimer des bibliothèques données ou tout à partir du dossier lib.

 // print library versions (jersey-common.jar, jackson-core-2.6.1.jar) try { List jars = Arrays.asList( "jersey-common", "jackson-core", "openjpa", "mylib" ); SsortingngBuilder verbuf = new SsortingngBuilder(); for(File file : new File("/opt/tomcat/webapps/myapp/WEB-INF/lib/").listFiles() ) { Ssortingng name = file.getName(); if (file.isDirectory() || !file.isFile() || !name.endsWith(".jar") ) continue; name = name.subssortingng(0, name.length()-4); boolean found = jars.contains(name); if (!found) { int idx = name.lastIndexOf('-'); if (idx>0) found = jars.contains( name.subssortingng(0, idx) ); } if (!found) continue; JarFile jarFile = new JarFile(file, false); try { Ssortingng ver; Manifest mf = jarFile.getManifest(); if (mf!=null) { ver = mf.getMainAtsortingbutes().getValue("Bundle-Version"); if (ver==null || ver.isEmpty()) ver = mf.getMainAtsortingbutes().getValue("Implementation-Version"); } else ver=null; if (verbuf.length()>0) verbuf.append(", "); verbuf.append(name + "=" + (ver!=null?ver:"") ); } finally { jarFile.close(); } } System.out.println( verbuf.toSsortingng() ); } catch(Exception ex) { ex.printStackTrace(); }