2010-11-08 22 views
14

Io uso questo codice nel mio programma per caricare un file di proprietà:jar eseguibile non troverà le proprietà dei file

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

Il codice viene eseguito bene in Eclipse. Quindi impacchetta il programma in un JAR chiamato MyProgram.jar, e lo eseguo, ho ottenuto un NullPointerException sulla seconda riga. Il JAR non contiene il file delle proprietà, entrambi si trovano nella stessa directory. Sto usando Maven per creare il JAR. Come posso risolvere questo problema?

UPDATE: Non voglio aggiungere il file delle proprietà al JAR, poiché verrà creato al momento della distribuzione.

+2

laterale: C'è qualche motivo per cui stai usando 'getResource()' invece di 'getResourceAsStream()', visto che lo stai usando come stream comunque? – Powerlord

+1

No, non ho alcuna ragione particolare. –

+0

Come gestisci il tuo barattolo? Se tramite java -jar, puoi provare java -cp ./MyProgram.jar e vedere se funziona? –

risposta

23

BalusC ha ragione, è necessario istruire Maven per generare un MANIFEST.MF con la directory corrente (.) nella voce Class-Path:.

Supponendo che si sta ancora utilizzando l'Assemblea Plugin Maven e il descrittore jar-with-dependencies per costruire il tuo JAR eseguibile, si può dire al plugin per farlo utilizzando il seguente:

<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> 
+0

Se non si utilizza il plug-in di assembly di maven, fammelo sapere e aggiornerò la mia risposta. –

+0

Con la sezione 'executions', non devo eseguire' mvn assembly: assembly' separatamente, giusto? A proposito, grazie per aver risposto a tutte le mie domande su Maven. –

+1

@HaiMinhNguyen: In effetti, il precedente 'execution' lega l'obiettivo' single' nella fase 'package'. Di conseguenza, l'esecuzione di 'mvn package' crea l'assembly. Oh, e tu sei il benvenuto –

2

EDIT: questo è quello di rispondere al tuo commento:

È necessario assicurarsi che il file delle proprietà è sulla strada di classe con la radice di destra per l'invocazione java che le stelle il file jar. se il percorso è

stuff/things.properties

e la posizione di runtime è

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

e il file jar si trova nella

/opt/myapp/bin/myjar

allora avete bisogno di lanciare come

/path/to/java -cp "/opt/myapp/etc:/opt/myapp/bin/myjar.jar" my.pkg.KavaMain

lavorare con questo tipo di configurazione può essere fastidioso in un dev ambiente, per fortuna, c'è lo maven exec plugin che ti porterà nel giusto tipo di scenario di lancio.

risposta originale:

Si vuole leggere su the maven resources plugin.

Fondamentalmente si desidera aggiungere qualcosa di simile:

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

al vostro pom.xml supponendo che sei propertis file è con le sorgenti di Java - in realtà dovrebbe essere in src/main/resources.

+0

Grazie, ma non voglio aggiungere il file delle proprietà al JAR. Sarà cambiato al momento dell'implementazione. –

+0

Come per la tua modifica: l'argomento '-cp' è ** ignorato ** quando si usa l'argomento' -jar'. Deve davvero andare nel file 'MANIFEST.MF' :) – BalusC

+0

@BalusC righto, risolto. Impossibile andare in MANIFEST.MF se può spostarsi in fase di esecuzione. – lscoughlin

17

ci sono due soluzioni alternative :

  1. Non utilizzare il JAR come executabele JAR, ma come biblioteca.

    java -cp .;filename.jar com.example.YourClassWithMain 
    
  2. ottenere la posizione radice del file JAR e ottenere il file delle proprietà da esso.

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

Nessuno dei due approcci sono raccomandati!L'approccio raccomandare è quello di avere la seguente voce nel file di JAR di /META-INF/MANIFEST.MF:

Class-Path: . 

allora sarà disponibile come risorsa classpath solito modo. Dovrai davvero istruire Maven in qualche modo per generare il file MANIFEST.MF in questo modo.

+0

Oops Ho provato prima la prima opzione ma l'ho usata. COMMA nomefile.jar. Forse è per questo che non ha funzionato. Grazie per l'aiuto. –

+0

C'è un motivo per evitare il Classpath, vale a dire se il contenuto cambia tra le letture. Il caricatore di risorse memorizza nella cache il primo contenuto –

0

ho avuto un problema simile, e questa discussione è stata di grande aiuto! Cordiali saluti, ho modificato il mio BuildFile Ant per fare il manifesto-making, quindi designato che si manifestano quando JAR-ing mio codice lato server: Nota

<!-- 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"> 
[....] 
Problemi correlati