Come faccio a leggere il file manifest per una webapp in esecuzione in apache tomcat?

Ho una webapp che contiene un file manifest, in cui scrivo la versione corrente della mia applicazione durante un’operazione di compilazione ant. Il file manifest è stato creato correttamente, ma quando provo a leggerlo durante il runtime, ottengo alcuni strani effetti collaterali. Il mio codice per la lettura nel manifest è qualcosa del genere:

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

Quando allego eclipse su tomcat, vedo che il codice sopra funziona, ma sembra che abbia un file manifest differente da quello che mi aspettavo, che posso dire perché la versione ant e la data / ora di compilazione sono entrambe differenti. Quindi, inserisco “META-INFFFF” e il codice sopra funziona ancora! Ciò significa che sto leggendo qualche altro manifesto, non il mio. Ho anche provato

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

Ma il risultato è stato lo stesso. Qual è il modo corretto di leggere il file manifest dall’interno di una webapp in esecuzione in tomcat?

Modifica : Grazie per i suggerimenti finora. Inoltre, devo notare che sto eseguendo Tomcat standalone; Lo avvio dalla riga di comando e quindi si collega all’istanza in esecuzione nel debugger di Eclipse. Questo non dovrebbe fare la differenza, dovrebbe?

Forse i tuoi effetti collaterali derivano dal fatto che quasi tutti i barattoli includono un MANIFEST.MF e non stai ottenendo quello giusto. Per leggere MANIFEST.MF dalla webapp, direi:

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

Tieni presente che l’esecuzione di Tomcat da Eclipse non è la stessa cosa che eseguire Tomcat da solo mentre Eclipse gioca con il classloader.

un po ‘tardi, ma questo funziona per me (web appl in Glassfish)

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

Prova a usare jcabi-manifests , che fa tutto questo lavoro di caricamento per te. Per esempio:

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

carica l’attributo My-Version da uno dei file MANIFEST.MF disponibili.

Importante ricordare che (maggiori dettagli sono disponibili qui ) nella maggior parte dei contenitori Web il programma di caricamento class thread corrente non è lo stesso del caricatore class contesto servlet. Ecco perché è necessario aggiungere il contesto di servlet al registro in runtime ( maggiori informazioni ):

 Manifests.append(servletContext); 

Inoltre, controlla questo: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

Il modo predefinito in cui i programmi di caricamento delle classi funzionano è di rimandare al genitore prima di tentare di cercare le proprie risorse. Quindi se un caricatore di class genitore ha qualche manifest disponibile, questo è ciò che otterrai. Di fatto, i server delle app non lo fanno necessariamente, per consentire alle applicazioni di sovrascrivere le versioni delle librerie. Inoltre, i caricatori di classi possono avere più vasi e quindi più manifesti.

Potrebbe essere in grado di ottenere un URL di risorsa di una delle risorse denominate in modo univoco. Apri una connessione. JarURLConnection a JarURLConnection . Ottieni il JarFile . Carica il manifest da quello. Potrebbe non funzionare, specialmente se Tomcat esplode la guerra.

[Aggiornamento] Naturalmente, il file di guerra non è sul classpath. Il classpath avrà qualcosa come WEB-INF / lib / ( .jar | .zip) e WEB-INF / classs /. Ottenere una risorsa da ServletContext dovrebbe funzionare.

La migliore soluzione: fare qualcosa di diverso. 🙂

Il manifest giusto esiste nella root dell’applicazione sul server. Scopri la radice dell’appication, ad esempio individuando classpath della tua class:

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

Quindi sostituire il percorso sopra con il percorso stabilito: Esempio di Glassfish:

 /applications//META-INF/MANIFEST.MF 

Funziona per me.

Non so su un modo “ufficiale” di leggerlo, ma se MANIFEST.MF non può essere caricato correttamente come risorsa, come fare per cercare di derivarne il percorso da “ServletContext.getRealPath ()” su qualche percorso web definito nella tua app?

Scrivere la versione dell’app anche in un altro posto (un file di proprietà in WEB-INF / classi) da formica durante la compilazione è un’altra soluzione che mi viene in mente.

Questo è quello che faccio per stampare varie versioni in un file di log. Ho hardcoded un percorso espanso ma le app possono usare servletContext.getRealPath("/") per leggere un percorso completo alla cartella webapp. Può stampare solo le librerie fornite o qualsiasi cosa dalla cartella lib.

 // print library versions (jersey-common.jar, jackson-core-2.6.1.jar) try { List jars = Arrays.asList( "jersey-common", "jackson-core", "openjpa", "mylib" ); StringBuilder verbuf = new StringBuilder(); for(File file : new File("/opt/tomcat/webapps/myapp/WEB-INF/lib/").listFiles() ) { String name = file.getName(); if (file.isDirectory() || !file.isFile() || !name.endsWith(".jar") ) continue; name = name.substring(0, name.length()-4); boolean found = jars.contains(name); if (!found) { int idx = name.lastIndexOf('-'); if (idx>0) found = jars.contains( name.substring(0, idx) ); } if (!found) continue; JarFile jarFile = new JarFile(file, false); try { String ver; Manifest mf = jarFile.getManifest(); if (mf!=null) { ver = mf.getMainAttributes().getValue("Bundle-Version"); if (ver==null || ver.isEmpty()) ver = mf.getMainAttributes().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.toString() ); } catch(Exception ex) { ex.printStackTrace(); }