Исполняемый файл не найдет файлы свойств - PullRequest
15 голосов
/ 08 ноября 2010

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

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

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

ОБНОВЛЕНИЕ: я не хочу добавлять файл свойств в JAR, так как он будет создан во время развертывания.

Ответы [ 4 ]

23 голосов
/ 09 ноября 2010

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

Предполагая, что вы по-прежнему используете подключаемый модуль Maven 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>
18 голосов
/ 08 ноября 2010

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

  1. Не используйте JAR как исполняемый 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 JAR:

Class-Path: .

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

2 голосов
/ 08 ноября 2010

РЕДАКТИРОВАТЬ: это для ответа на ваш комментарий:

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

stuff / things.properties

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

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

и файл jar находится в

/ opt / myapp / bin / myjar

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

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

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

Оригинальный ответ:

Вы хотите прочитать о плагине ресурсов maven .

По сути, вы хотите добавить что-то вроде этого:

<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, предполагая, что вы имеете файл с исходными файлами Java - на самом деле это должно быть в src / main / resources.

0 голосов
/ 10 января 2011

У меня была похожая проблема, и эта тема очень помогла!К вашему сведению, я изменил свой сборочный файл Ant для выполнения MANIFEST, а затем назначил этот манифест при 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">
[....]
...