web-dev-qa-db-fra.com

Le fichier jar exécutable ne trouvera pas les fichiers de propriétés

J'utilise ce code dans mon programme pour charger un fichier de propriétés:

Properties properties = new Properties();
URL url = new App().getClass().getResource(PROPERTIES_FILE);
properties.load(url.openStream());

Le code fonctionne bien dans Eclipse. Ensuite, je compresse le programme dans un fichier JAR nommé MyProgram.jar et l'exécute. J'ai reçu une exception NullPointerException à la deuxième ligne. Le fichier JAR ne contient pas le fichier de propriétés, ils sont tous deux dans le même répertoire. J'utilise Maven pour créer le fichier JAR. Comment puis-je résoudre ce problème?

UPDATE: je ne souhaite pas ajouter le fichier de propriétés au fichier JAR, car il sera créé au moment du déploiement.

15
Hai Minh Nguyen

BalusC a raison, vous devez demander à Maven de générer un MANIFEST.MF avec le répertoire actuel (.) dans l’entrée Class-Path:.

En supposant que vous utilisiez toujours le plug-in Maven Assembly et le descripteur jar-with-dependencies pour construire votre fichier JAR exécutable, vous pouvez indiquer au plug-in de le faire en utilisant les éléments suivants:

  <plugin>
    <artifactId>maven-Assembly-plugin</artifactId>
    <version>2.2</version>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>com.stackoverflow.App</mainClass>
        </manifest>
        <manifestEntries>
          <Class-Path>.</Class-Path> <!-- HERE IS THE IMPORTANT BIT -->
        </manifestEntries>
      </archive>
    </configuration>
    <executions>
      <execution>
        <id>make-Assembly</id> <!-- this is used for inheritance merges -->
        <phase>package</phase> <!-- append to the packaging phase. -->
        <goals>
          <goal>single</goal> <!-- goals == mojos -->
        </goals>
      </execution>
    </executions>
  </plugin>
23
Pascal Thivent

Il existe deux solutions de contournement

  1. N'utilisez pas le fichier JAR en tant que fichier JAR exécutable, mais en tant que bibliothèque.

    Java -cp .;filename.jar com.example.YourClassWithMain
    
  2. Obtenez l'emplacement racine du fichier JAR et récupérez le fichier de propriétés.

    URL root = getClass().getProtectionDomain().getCodeSource().getLocation();
    URL propertiesFile = new URL(root, "filename.properties");
    Properties properties = new Properties();
    properties.load(propertiesFile.openStream());
    

Aucune des deux ne sont des approches recommandées! L'approche recommandée consiste à avoir l'entrée suivante dans le fichier /META-INF/MANIFEST.MF du fichier JAR:

Class-Path: .

Ensuite, il sera disponible comme ressource classpath de la manière habituelle. Vous devrez vraiment demander à Maven de générer le fichier MANIFEST.MF de cette manière.

18
BalusC

EDIT: ceci est pour répondre à votre commentaire:

Vous devez vous assurer que le fichier de propriétés se trouve sur le chemin de classe avec la bonne racine pour l'appel Java qui insère le fichier jar. si votre chemin est 

trucs/choses.properties 

et l'emplacement d'exécution est 

/opt/myapp/etc/stuff/things.properties 

et le fichier jar est dans 

/ opt/myapp/bin/myjar 

alors vous devez lancer en tant que 

/ chemin/vers/Java -cp "/opt/myapp/etc:/opt/myapp/bin/myjar.jar" my.pkg.KavaMain 

travailler avec ce type de configuration peut être fastidieux dans un environnement de développement. Heureusement, il existe le plugin maven exec qui vous donnera le bon type de scénario de lancement.

Réponse originale:

Vous voulez en savoir plus sur le plugin maven resources .

En gros, vous voulez ajouter quelque chose comme ceci:

<plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
                <resources>
                        <resource>
                                <directory>src/main/Java</directory>
                                <includes>
                                        <include>**/*properties</include>
                                </includes>
                        </resource>
                </resources>
        </configuration>
<plugin>

sur votre fichier pom.xml en supposant que votre fichier de propriété est avec vos sources Java - en réalité, il devrait être dans src/main/resources.

2
lscoughlin

J'ai eu un problème similaire, et ce fil était d'une grande aide! Pour votre information, j'ai modifié mon fichier de génération Ant pour effectuer la création de MANIFEST, puis j'ai désigné ce manifeste lorsque JAR-ing mon code côté serveur

<!-- Create a custom MANIFEST.MF file, setting the classpath. -->
<delete file="${project.base.dir}/resources/MANIFEST.MF" failonerror="false"/>
<manifest file="${project.base.dir}/resources/MANIFEST.MF">
  <attribute name="Class-Path" value="." />
</manifest>

<!-- JAR the server-side code, using the custom manifest from above. -->
<jar destfile="services/${name}.aar" manifest="${project.base.dir}/resources/MANIFEST.MF">
[....]
0
Daniel F. Thornton