2010-04-16 17 views
12

Ho un'applicazione Web che utilizza una libreria che risiede in TOMCAT_HOME/common/lib. Questa libreria cerca un file di proprietà alla radice del classpath (in una classe chiamata ApplicationConfig):getResourceAsStream non carica risorse in webapp

ApplicationConfig.class.getResourceAsStream("/hv-application.properties"); 

applicazione web Il mio Tomcat contiene questo file di proprietà. È in WEB-INF/classes, che è la radice del classpath giusto? Tuttavia, durante il runtime, quando tenta di caricare il file delle proprietà, genera un'eccezione perché non riesce a trovarla (getResourceAsStream restituisce null).

Tutto funziona correttamente se la mia applicazione è un'applicazione Java semplice e autonoma. Tomcat fa in modo che il metodo getResourceAsStream agisca diversamente? So che ci sono un sacco di domande simili là fuori, ma nessuno di loro ha purtroppo contribuito. Grazie.

risposta

22

Prova Thread.currentThread().getContextClassLoader().getResourceAsStream("/hv-application.properties") invece.

+0

Grazie binil. Funziona, ma preferirei non dover apportare modifiche alla libreria. Contrassegna come risposta se non vengono trovate altre soluzioni. – Michael

+3

Stranamente, in Tomcat 5.5 con Win XP e JDK 1.5.08 sono stato in grado di caricare un file di risorse senza utilizzare il "/" iniziale. In realtà quando prepending il "/", stavo incontrando problemi. – Olivier

1

Il gestore della sicurezza Tomcat generalmente non ti consente di accedere alle classi e alle risorse webapp dalle librerie nelle librerie root di Tomcat. Questo ha lo scopo di dare una separazione tra le applicazioni web in esecuzione in un contenitore.

Si dovrebbe essere in grado di aggirare questo aggiornando la politica di sicurezza, ma generalmente è meglio non inserire le proprie librerie nel contenitore Tomcat, cosa che presumo si stia facendo.

+1

La domanda dice chiaramente che la risorsa si trova nella directory WEB-INF/classes ... – Pointy

+0

@stevedbrown, l'OP dice che il file è impacchettato insieme a WAR, all'interno di WEB-INF/classes. –

+0

Hai letto la prima frase? "Ho un'applicazione Web che utilizza una libreria che risiede in TOMCAT_HOME/common/lib. Questa libreria cerca un file di proprietà nella radice del classpath (in una classe chiamata ApplicationConfig):" – stevedbrown

2

Sembra che potrebbe essere correlato al funzionamento dei classloader Tomcat. Se hai qualcosa in un caricatore di classe (il tuo file di configurazione nel classloader webapp) che è usato da qualcosa in un altro (il jar in comune/lib), il risultato potrebbe essere un grosso mal di testa.

Questo document spiega come Tomcat delega ai caricatori di classe. Se possibile, puoi provare uno dei seguenti:

  1. Spostare il file jar in common/lib nell'applicazione Web (WEB-INF/lib). Questo non è sempre possibile, lo so, ma a volte i barattoli (ad esempio log4j) possono coesistere pacificamente tra i classloader (*).
  2. Sposta il file di configurazione in comune/classi. Questa è effettivamente la stessa cosa (mette l'elemento di configurazione nello stesso classloader del jar che ne ha bisogno). Di nuovo, questo non è l'ideale, ma se hai il controllo sul tuo ambiente, funzionerebbe.

In entrambi i casi, avere risorse in diversi classloader può essere un problema. Spero che aiuti.

(*) log4j ha l'opzione -log4j.ignoreTCL che rende questo possibile, anche se

+0

Grazie Andy, ho provato a spostare il mio file di configurazione in common/classes, ma non ha funzionato. La mia webapp è l'unica webapp che usa questa libreria, quindi forse la sposterò in WEB-INF/lib (anche se sarebbe un po 'un dolore perché dovrei modificare il mio Maven pom per farlo includere il JAR). – Michael

+0

È meglio conservare tutti i vasi nella tua webapp. Il più delle volte questo è possibile, ma ci sono circostanze in cui lo spostamento di cose in comune/lib (come se si sta facendo una risorsa che deve essere disponibile attraverso il server). –

0

sto espandendo Olivier comment come risposta (grazie per il piombo).

Il problema sembra essere la barra iniziale (/) nel percorso della risorsa.

In Tomcat 8 il WebAppClassloader risolve correttamente il percorso con e senza la principale. Entrambi .getResourceAsStream("/org/pakopa/app/config.properties"); e .getResourceAsStream("org/pakopa/app/config.properties"); restituiscono un InputStream.

In Tomcat 7 (e presumo versioni precedenti troppo) .getResourceAsStream("/org/pakopa/app/config.properties"); non è stato risolto e restituisce null ma .getResourceAsStream("org/pakopa/app/config.properties"); viene risolto correttamente.

Problemi correlati