2010-11-08 2 views
14

Я использую этот код в моей программе, чтобы загрузить файл свойств:Исполняемые банку не найти файлы свойств

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

код прекрасно работает в Eclipse. Затем я упаковываю программу в JAR с именем MyProgram.jar и запускаю ее, я получил исключение NullPointerException во второй строке. JAR не содержит файл свойств, они оба находятся в одном каталоге. Я использую Maven для создания JAR. Как я могу исправить эту проблему?

UPDATE: я не хочу добавлять файл свойств в JAR, так как он будет создан во время развертывания.

+2

Side Примечание: Есть ли какая-либо причина вы используете 'getResource()' вместо 'getResourceAsStream()', так как вы просто используете его как поток в любом случае? – Powerlord

+1

Нет, у меня нет особых причин. –

+0

Как вы управляете своей банкой? Если через java -jar вы можете попробовать java -cp ./MyProgram.jar и посмотреть, работает ли он? –

ответ

23

BalusC является правильным, вам необходимо указать Maven для создания MANIFEST.MF с текущим каталогом (.) в записи Class-Path:.

Предполагая, что вы все еще используете Maven Plugin Assembly и jar-with-dependencies дескриптор построить свой исполняемый файл JAR, вы можете сказать, плагин, чтобы сделать это с помощью следующих действий:

<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

Если вы не используете плагин сборки maven, сообщите мне, и я обновлю свой ответ. –

+0

В разделе 'executions' мне не нужно запускать' mvn assembly: assembly' отдельно право? Кстати, спасибо, что ответили на все мои вопросы о Maven. –

+1

@HaiMinhNguyen: Действительно, вышеупомянутое «исполнение» связывает цель «один» на фазе «пакет». В результате запуск 'mvn package' создает сборку. О, и ты же рад. –

2

EDIT: это ответить на ваш комментарий:

Вы должны убедиться, что файл свойств находится на пути к классам с правым корнем для Java вызова, что звезды на файл фляги. если ваш путь

вещи/things.properties

и место выполнения является

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

и файл банку в

/Opt/MyApp/bin/myjar

, то вам нужно запустить в

/путь/к/Java -cp «/opt/myapp/etc:/opt/myapp/bin/myjar.jar» my.pkg.KavaMain

работы с такого рода конфигурации может быть утомительным в разработчика к счастью, есть maven exec plugin, который даст вам правильный сценарий запуска.

Оригинал Ответ:

Вы хотите прочитать о the maven resources plugin.

В основном вы хотите добавить что-то вроде этого:

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

на ваш pom.xml при условии, что вы Propertis файл с источниками Java - на самом деле это должно быть в SRC/основные/ресурсов.

+0

Спасибо, но я не хочу добавлять файл свойств в JAR. Он будет изменен во время развертывания. –

+0

В соответствии с вашими изменениями: аргумент '-cp' ** игнорируется ** при использовании аргумента' -jar'. У него действительно есть файл 'MANIFEST.MF' :) – BalusC

+0

@BalusC righto, исправлено. Невозможно войти в MANIFEST.MF, если он может перемещаться во время выполнения. – lscoughlin

17

Есть два обходные:

  1. Не используйте БАНКУ как executabele JAR, но, как библиотеки.

    java -cp .;filename.jar com.example.YourClassWithMain 
    
  2. Получить корневой местоположение файла JAR и получить файл свойств от него.

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

Никто из обоих не рекомендуются подходы!Рекомендуют подход иметь следующую запись в файле /META-INF/MANIFEST.MF банки:

Class-Path: . 

Тогда она будет доступна в качестве пути к классам ресурса обычным способом. Вам действительно нужно будет указать Maven для создания файла MANIFEST.MF.

+0

К сожалению, я попробовал первый вариант раньше, но использовал. COMMA filename.jar. Возможно, поэтому это не сработало. Спасибо за вашу помощь. –

+0

Существует одна причина для исключения пути к классу - а именно, если содержимое изменяется между чтениями. Загрузчик ресурсов кэширует первое содержимое –

0

У меня была аналогичная проблема, и эта нить была большой помощью! FYI, я изменил мой Ant Buildfile делать манифест решений, а затем назначенными что манифест, когда JAR-кий мой код на стороне сервера:

<!-- 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"> 
[....] 
Смежные вопросы