Ответ 1
по этой ссылке:
Как: Eclipse Maven установить сборку с зависимостями
Я узнал, что это не работоспособное решение, потому что загрузчик классов не загружает банки из банок, поэтому я думаю, что я распакую зависимости внутри банки.
Я использую Maven в своем автономном приложении и хочу упаковать все зависимости в моем JAR файле внутри папки библиотеки, как указано в одном из ответов здесь:
Как создать исполняемый JAR с зависимостями с помощью Maven?
Я хочу, чтобы в моем последнем JAR файле была папка с библиотекой, которая содержит зависимости как файлы JAR, а не то, что maven-shade-plugin
помещает зависимости в виде папок, таких как иерархия Maven в папке .m2.
Ну, на самом деле текущая конфигурация делает то, что я хочу, но у меня возникла проблема с загрузкой файлов JAR при запуске приложения. Я не могу загрузить классы.
Здесь моя конфигурация:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.myapp.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>install</id>
<phase>install</phase>
<goals>
<goal>sources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
Проект отлично работает с Eclipse, а файлы JAR помещаются в папку библиотеки внутри моего финального JAR файла, как я хочу, но при запуске финального файла JAR из целевой папки я всегда получаю ClassNotFoundException
:
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext
Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContext
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: com.myapp.MainClass. Program will exit.
Как я могу исправить это исключение?
по этой ссылке:
Как: Eclipse Maven установить сборку с зависимостями
Я узнал, что это не работоспособное решение, потому что загрузчик классов не загружает банки из банок, поэтому я думаю, что я распакую зависимости внутри банки.
Следующее - мое решение. Проверьте его, если он работает для вас:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!-- <classpathPrefix>lib</classpathPrefix> -->
<!-- <mainClass>test.org.Cliente</mainClass> -->
</manifest>
<manifestEntries>
<Class-Path>lib/</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
Первый плагин помещает все зависимости в папку target/classes/lib, а второй включает библиотечную папку в конечном JAR файле и настраивает файл Manifest.mf
.
Но тогда вам нужно будет добавить пользовательский код загрузки классов для загрузки файлов JAR.
Или, чтобы избежать пользовательской загрузки классов, вы можете использовать "$ {project.build.directory}/lib, но в этом случае у вас нет зависимостей внутри финального файла JAR, который побеждает цель.
Прошло два года с тех пор, как был задан вопрос. Тем не менее проблема с вложенными файлами JAR сохраняется. Надеюсь, это поможет кому-то.
Самый простой и эффективный способ - использовать плагин uber следующим образом:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<finalName>uber-${artifactId}-${version}</finalName>
</configuration>
</plugin>
У вас будет нормализован все в одном файле JAR.
Обновлено:
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
исполняемый плагин maven plugin можно использовать именно для этой цели: создание автономных java-приложений, содержащих все зависимости в виде файлов JAR в определенной папке.
Просто добавьте следующее в pom.xml
в раздел <build><plugins>
(обязательно замените значение mainClass
соответственно):
<plugin>
<groupId>de.ntcomputer</groupId>
<artifactId>executable-packer-maven-plugin</artifactId>
<version>1.0.1</version>
<configuration>
<mainClass>com.example.MyMainClass</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>pack-executable-jar</goal>
</goals>
</execution>
</executions>
</plugin>
Созданный JAR файл находится в target/<YourProjectAndVersion>-pkg.jar
после запуска mvn package
. Все его зависимости от времени компиляции и времени выполнения будут включены в папку lib/
внутри JAR файла.
Отказ от ответственности: я являюсь автором плагина.
Вот как я это делаю:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.project.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
А потом я просто запустил:
mvn assembly:assembly
Я нашел этот ответ на вопрос:
http://padcom13.blogspot.co.uk/2011/10/creating-standalone-applications-with.html
Вы не только получаете зависимые файлы lib в папке lib, но также получаете директорию bin с исполняемым файлом unix и dos.
В конечном итоге исполняемый файл вызывает java с аргументом -cp, в котором также перечислены все ваши зависимые библиотеки.
Весь пакет находится в папке appasembly внутри целевой папки. Эпическая.
============= Да, я знаю, что это старая нить, но она все еще приближается к результатам поиска, поэтому я подумал, что это может помочь кому-то вроде меня.
Это явно проблема с classpath. Учтите, что путь к классам должен немного измениться при запуске вашей программы вне среды IDE. Это связано с тем, что IDE загружает другие JAR файлы относительно корневой папки вашего проекта, в то время как в случае окончательного JAR это обычно неверно.
В этих ситуациях мне нравится делать JAR вручную. Это занимает не более 5 минут, и это всегда решает проблему. Я не предлагаю вам это делать. Найдите способ использовать Maven, что его цель.