Пользуюсь средой разработки NetBeans. Собираю с помощью Ant.
Проблема заключается вот в чем: Например у меня есть какой-то проект с библиотеками в папке lib и некоторыми файлами в папке src. Объекты создаваемые в этом проекте используют данные библиотеки и файлы. Далее если я собираю данный проект в jar и кладу в библиотеку другого проекта, а потом использую объекты классов из данного jar то выпадает ислючение, что не хватает библиотек, либо файла по данному пути не существует. Соответственно, если добавить данные библиотеки и файлы в новый проект, то все работает. Но в jar они есть!!! Как сделать так чтобы объекты классов создаваемых из jar использовали данные ресурсы из своего jar?
Вот абстрактный пример: Проект "А" из которого мы собираем jar и котором лежит файл hello.txt
package inner.ru;
import java.io.File;
public class Check {
private final File file = new File("src//inner//file//hello.txt");
public void print() {
System.out.println(file.exists());
}
}
Проект "B" в который в библиотеку мы кладем данный jar
package external.main;
import inner.ru.Check;
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Check check = new Check();
check.print();
}
}
Соответственно если во второй проект положить файл hello.txt, то получим true, но он уже лежит в первом проекте, и мне надо, чтобы он брал его именно оттуда.
Вы обращаетесь к файлу по относительному пути:
private final File file = new File("src//inner//file//hello.txt");
т.е. Вы ссылаетесь на файл, который лежит в папке src\inner\file относительно папки, в которой запущено приложение, а не к файлу, который запакован в JAR.
Когда Вы запускаете первый проект из Netbeans, он устанавливает текущую папку в корневой каталог проекта и код находит файл в папке исходников. Если Вы вытащите собранный JAR, перенесете его в отдельную папку и запустите его вручную там, то произойдет ошибка, т.к. папки src уже не будет. По той же причине ошибка возникает при запуске из второго проекта (файла нет в исходниках).
Возможные решения:
Вынести файл из проектов вообще и обращаться к нему по абсолютному пути (c:\\Projects....\hello.txt). В этом случае добавлять файл в JAR не нужно. При переносе скажем, на другую машину, файл потребуется носить отдельно, но так он будет доступен всем проектам.
Если файл находится в пакете inner.file то можно обращаться к запакованному файлу как к ресурсу. Например, вот так можно вывести содержимое файла:
public void print() {
try (final InputStream stream = Check.class.getResourceAsStream("/inner/file/hello.txt")) {
java.util.Scanner s = new java.util.Scanner(stream);
while (s.hasNext()) {
System.out.println(s.nextLine());
}
} catch (IOException ex) {
System.out.println("File doesn't exist");
}
}
Здесь обращение идет именно к файлу, запакованному в JAR и, соответственно, файл будет доступен при использовании из других проектов.
Дополнение по библиотекам:
Та же проблема возникает с библиотеками. Используемые библиотеки не собираются в результирующий JAR файл. Соответственно, если проект inner использует библиотеку dependency.jar, которая не включена в проект external то при обращении к методам inner, которые зависят от dependency будут выброшены исключения.
Возможные решения:
Т.е. если external использует inner, то в него нужно добавить dependency.jar. При таком точечном подходе возможно более гибкое использование библиотек. Например, external может использовать более новую версию dependency, в этом случае может быть ненужно таскать за inner старые версии.
Посмотрите также на системы управления зависимостями: например, Maven или Ivy. Они существенно упрощают работу с библиотеками при сборке.
Можно также собрать inner таким образом, чтобы в одном JAR содержались все необходимые библиотеки.
Сделать это можно так:
build.xml — это скрипт сборки Ant, который находится в корне проекта. В Netbeans он отображается в окне «Файлы».<target name="package-for-store" depends="jar">
<!-- Замените MyJarName на имя, соответствуюее Вашему JAR
-->
<property name="store.jar.name" value="MyJarName"/>
<!-- don't edit below this line -->
<property name="store.dir" value="store"/>
<property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>
<echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/>
<delete dir="${store.dir}"/>
<mkdir dir="${store.dir}"/>
<jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip">
<zipgroupfileset dir="dist" includes="*.jar"/>
<zipgroupfileset dir="dist/lib" includes="*.jar"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
</manifest>
</jar>
<zip destfile="${store.jar}">
<zipfileset src="${store.dir}/temp_final.jar"
excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
</zip>
<delete file="${store.dir}/temp_final.jar"/>
</target>
build.xml и найти цель «package-for-store».store должен появиться JAR, с упакованными в него зависимостями. Его можно использовать в других проектах.Смотрите также:
Я при использовании Ant добавляю зависимые библиотеки и в один и в другой проект, то есть:
есть библиотека Y,
есть проект A,
который использует проект B,
который в свою очередь использует Y.
Я добавляю Y и к A и к B.
Вся фишка в том, как именно происходит сборка, например, если вы используете настройки Ant Netbeans по умолчанию, то зависимые библиотеки складываются в папку lib относительно основного jar файла и так прописываются в манифесте.
Если же вы подключаете другой проект как зависимый, jar файл этого проекта просто указывается библиотекой и так же помещается в папку lib.
Соответственно в манифесте проекта B указывается lib как папка с библиотеками для него, но этой папки нет, так как сам подключаемый jar проекта B уже лежит в lib.
Думаю, если Вам не хочется дублировать библиотеки, то зависимый проект B стоит собирать как один jar файл с упаковкой библиотек в него.
Продвижение своими сайтами как стратегия роста и независимости