it-swarm.com.ru

Исполняемый файл не найдет файлы свойств

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

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, так как он будет создан во время развертывания.

15
Hai Minh Nguyen

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>
23
Pascal Thivent

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

  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, подобного этому.

18
BalusC

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

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

вещи/things.properties 

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

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

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

/ Опт/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.

2
lscoughlin

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