2010-05-12 10 views
50

Je rencontre des problèmes lorsque l'un des fichiers jar dont dépend mon application tente de charger un fichier de propriétés dans le fichier jar. Voici le code dans le pot.Charger le fichier de propriétés dans JAR?

static 
{ 
    Properties props = new Properties(); 
    try 
    { 
     props.load(ClassLoader.getSystemResourceAsStream("someProps.properties")); 
    } catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
    someProperty = props.getProperty("someKey"); 
} 

Le fichier de propriétés est dans mon répertoire "src/main/resources" du projet Maven. Quand j'exécute ce code depuis mon test de junit dans Eclipse, il s'exécute très bien. Lorsque le projet est construit avec Maven dans un pot, et inclus comme une dépendance dans mon application webb, il ne parvient pas à localiser le fichier de propriétés. Je sais que le fichier de propriétés se trouve dans le répertoire de base du fichier jar, je ne sais pas comment résoudre ce problème.

Aidez s'il vous plaît!

Répondre

65

Le problème est que vous utilisez getSystemResourceAsStream. Utilisez simplement getResourceAsStream. Les ressources système sont chargées à partir du classloader système, qui n'est certainement pas le chargeur de classe dans lequel votre fichier jar est chargé lorsqu'il est exécuté en tant que webapp.

Cela fonctionne dans Eclipse parce que lors du lancement d'une application, le chargeur de classe système est configuré avec votre jar dans le cadre de son chemin de classe. (Par exemple, java -jar my.jar chargera my.jar dans le chargeur de classe système.) Ce n'est pas le cas des applications Web: les serveurs d'applications utilisent un chargement de classe complexe pour isoler les applications Web les unes des autres et celles du serveur d'applications. Par exemple, voir tomcat classloader how-to et le diagramme de la hiérarchie du chargeur de classe utilisé. EDIT: Normalement, vous appelez getClass(). GetResourceAsStream() pour récupérer une ressource dans le chemin de classe, mais comme vous récupérez la ressource dans un initialiseur statique, vous devrez nommer explicitement une classe qui est dans le classloader que vous voulez charger. L'approche la plus simple consiste à utiliser la classe contenant l'initialiseur statique, par exemple.

[public] class MyClass { 
    static 
    { 
    ... 
    props.load(MyClass.class.getResourceAsStream("/someProps.properties")); 
    } 
} 
+1

getContextClassLoader() en outre, utiliser comme dans 'Thread.currentThread le classloader contexte du thread()' –

+0

@binil T. écheveaux pour la pointe. Je n'ai jamais eu besoin de faire ça - quand est-ce nécessaire? – mdma

+1

@binil - J'ai étudié ce problème un petit peu, et je comprends que le classloader de contexte est utilisé lorsque vous voulez sortir de la hiérarchie de classloader et utiliser un chargeur de classe qui n'est pas l'un des ancêtres de votre classloader. Le classloader de contexte n'est pas nécessaire ici car la ressource est dans la même application web, et donc dans le même classloader que MyClass. – mdma

13

Pour mémoire, cela est documenté dans How do I add resources to my JAR? (illustré pour les tests unitaires, mais de même pour une ressource « régulière »):

Pour ajouter des ressources au classpath pour vos tests unitaires , vous suivez le même modèle que vous le faites pour ajouter des ressources au fichier JAR, sauf le répertoire où vous trouverez ressources dans ${basedir}/src/test/resources. A ce stade, vous auriez un projet structure de répertoire qui ressemblerait comme ce qui suit:

my-app 
|-- pom.xml 
`-- src 
    |-- main 
    | |-- java 
    | | `-- com 
    | |  `-- mycompany 
    | |   `-- app 
    | |    `-- App.java 
    | `-- resources 
    |  `-- META-INF 
    |   |-- application.properties 
    `-- test 
     |-- java 
     | `-- com 
     |  `-- mycompany 
     |   `-- app 
     |    `-- AppTest.java 
     `-- resources 
      `-- test.properties 

Dans un test unitaire, vous pouvez utiliser un simple bout de code comme suit pour accéder à la ressource nécessaire pour test:

... 

// Retrieve resource 
InputStream is = getClass().getResourceAsStream("/test.properties"); 

// Do something with the resource 

... 
+0

est-ce une structure standard, pour avoir des ressources dans 'test' et' main'? Est-ce juste une convention Maven, ou une partie de la documentation JAR elle-même? – Thufir

Questions connexes