Basic Java Tools for Building & Testing Apps
Скачать 4.76 Mb.
|
Плагин создания jar-файла maven-jar-plugin Плагин maven-jar-plugin позволяет сформировать манифест, описать дополнительные ресурсы, необходимые для включения в jar-файл, и упаковать проект в jar-архив. Пример проектного файла pom.xml, описывающий настройку данного плагина : org.apache.maven.plugins maven-jar-plugin 2.4 **/properties/* **/*.png src/main/resources/META-INF/MANIFEST.MF В примере определена директория и манифест, включаемые в сборку. Тегом Плагин maven-jar-plugin может создать и включить в сборку MANIFEST.MF самостоятельно. Для этого следует в секцию true lib/ ru.company.AppMain Опции тега Определение префикса в Пример создания сборки (исполняемый jar-файл) с зависимостями библиотеки SWT можно посмотреть здесь Плагин тестирования maven-surefire-plugin Плагин maven-surefire-plugin предназначен для запуска тестов и генерации отчетов по результатам их выполнения. По умолчанию на тестирование запускаются все java-файлы, наименование которых начинается с «Test» и заканчивается «Test» или «TestCase» : **/Test*.java **/*Test.java **/*TestCase.java Если необходимо запустить java-файл с отличным от соглашения наименованием, например Sample.java, то необходимо в проектный файл pom.xml включить соответствующую секцию с плагином maven-surefire-plugin. org.apache.maven.plugins maven-surefire-plugin 2.12.4 Sample.java Плагин maven-surefire-plugin содержит единственную цель surefire:test. Для разработки кодов тестирования можно использовать как JUnit , так и TestNG. Результаты тестирования в виде отчетов в форматах .txt и .xml сохраняются в директории ${basedir}/target/surefire-reports. Иногда приходится отдельные тесты исключать. Это можно сделать включением в секцию org.apache.maven.plugins maven-surefire-plugin 2.12.4 **/TestCircle.java **/TestSquare.java Чтобы запустить проект на тестирование необходимо выполнить одну из следующих команд : mvn test mvn -Dmaven.surefire.debug test Чтобы пропустить выполнение тестов на этапе сборки проекта, можно выполнить команду. mvn clean package -Dmaven.test.skip=true Также можно проигнорировать выполнение тестирования проекта включением в секцию true Плагин генерации номера сборки buildnumber-maven-plugin Предположим, что нам нужно в манифест MANIFEST.MF нашего WEB-приложения и в файл свойств src/main/resources/app.properties положить номер сборки, который определяется переменной ${buildNumber}. Файл манифеста будем генерить автоматически. А в файл свойств проекта app.properties включим параметры, значения которых будут определяться на этапе сборки проекта : # application.properties app name = $ { pom name } app version = $ { pom version } app build = $ { buildNumber } В режиме выполнения программы (runtime) можно обращаться к данному файлу свойств для получения наименования приложения и номера версии сборки. Для генерирования уникального номера сборки проекта используется плагин buildnumber- maven-plugin. Найти плагин можно в репозитории в директории ${M2_HOME}/repository/org/codehaus/mojo. Пример настройки плагина в проектном файле pom.xml : 4.0.0 ru.hellogwt.sample hellogwt war 1.0 GWT Maven Archetype org.codehaus.mojo buildnumber-maven-plugin 1.2 validate create true {0}-{1,date,yyyyMMdd} ${project.version} timestamp В приведенном примере плагин запускается во время фазы жизненного цикла validate и генерирует номер версии ${buildNumber}, который собирается из нескольких частей и определен тэгом Если в pom.xml не настроена работа с SCM (Source Code Management) типа Subversion, Git и т.п., то при попытке генерации номера сборки будет получено сообщение об ошибке "The scm url cannot be null". В этом случае можно указать в pom.xml заглушку SCM. scm:svn:http://127.0.0.1/dummy scm:svn:https://127.0.0.1/dummy HEAD http://127.0.0.1/dummy Чтобы номер сборки генерировался независимо от подключения к SCM в настройках конфигурации плагина следует указать свойство revisionOnScmFailure равным true. Теперь настроим плагин maven-war-plugin, чтобы номер версии поместить в MANIFEST.MF, который будет создаваться автоматически : org.apache.maven.plugins maven-war-plugin 2.6 true ${buildNumber} Генерируемое значение, по-умолчанию, сохраняется в файле ${basedir}/buildNumber.properties и имеет имя buildNumber. При необходимости данные параметры могут быть переопределены через свойства buildNumberPropertiesFileLocation и buildNumberPropertyName соответственно. Чтобы определить значения в файле свойств src/main/resources/app.properties включим фильтрацию ресурсов в разделе src/main/resources true Дополнительную информацию о фильтрации для корректировки значений в файле свойств *.properties можно почитать здесь После выполнения сборки проекта манифест MANIFEST.MF в файле .war будет иметь приблизительно следующий вид : Manifest - Version : 1.0 Implementation - Title : GWT Maven Archetype Implementation - Version : 1.0 Implementation - Vendor - Id : ru hellogwt sample Built - By : Father Build - Jdk : 1.7 0_67 Created - By : Apache Maven 3.3 9 Implementation - Build : 1.0 - 20161001 Archiver - Version : Plexus Archiver Конечно же изменится и файл свойств app.properties в сборке : # application.properties app name = GWT Maven Archetype app version = 1.0 app build = 1.0 - 20161001 Чтобы в сервлете WEB-приложения прочитать версию сборки в файле MANIFEST.MF можно использовать следующий код : import java io IOException ; import java util Properties ; String version = "UNDEFINED" ; Properties prop = new Properties (); try { prop load ( getServletContext (). getResourceAsStream ( "/META-INF/MANIFEST.MF" )); version = prop getProperty ( "Implementation-Build" ); } catch ( IOException e ) {} Наследование проектов в maven Одним из важных аспектов многомодульного приложения является возможность независимой разработки отдельных модулей, обеспечивая, таким образом, расширение и изменение функциональности системы в целом. И здесь существенную помощь разработчикам оказывает фреймворк maven , который позволяет связать все проекты системы в единое целое. Чтобы объединить несколько maven-проектов в один связанный проект необходимо использовать наследование, которое определяет включение дополнительных секций в pom.xml (POM - Project Object Model). Допустим необходимо разработать два взаимосвязанных проекта (project1, project2), которые должны быть объединены в едином родительском проекте project. Физически проекты необходимо расположить в одной родительской директории, в которой дочерние maven- проекты являются поддиректориями. Родительский файл pom.xml располагается в корневой директории, как это представлено на следующем скриншоте : Настройка родительского pom.xml В pom.xml родительского проекта необходимо определить параметры GAV (groupId, artifactId, version) и в теге указать значение «pom». Дополнительно вводится секция com.example project 0.0.1 pom project1 project2 Настройка дочерних pom.xml В pom.xml дочерних проектов необходимо ввести секцию и определить GAV- параметры родительского проекта. com.example project 0.0.1 На этом можно сказать, что все дочерние проекты привязаны к родительскому. Применение наследования maven Наследование в maven-проектах широко используется при разработке плагинов/бандлов для контейнеров OSGi (Open Services Gateway Initiative) и компонентов EJB (Enterprise JavaBeans). Также можно использовать «преимущества» наследования и в простых проектах. Зачем объединять проекты? В связанных многомодульных проектах можно исключить дублирование свойств и зависимостей, а также использовать централизованное управление и контролировать зависимости. 1. Общие свойства проектов Связанные проекты позволяют определить общие свойства проектов, зависимости и разместить их в родительском pom.xml. Дочерние проекты будут автоматически наследовать свойства родителя. В следующем примере создаются общие секции и 4.11 1.7 1.7 UTF-8 junit junit ${junit.version} test log4j log4j 1.2.17 Дочерние объекты наследуют значения следующих GAV-параметров родителя : 2. Централизованное управление проектами Выполняя maven-команды в родительском проекте, они автоматически будут выполнены для каждого из подпроектов. В следующем примере выполняется команда install, согласно которой после сборки всех проектов они будут размещены в локальном репозитории. $ cd project $ mvn install Таким образом, можно выполнять maven команды как для отдельного подпроекта, перемещаясь в его поддиректорию, так и для всех проектов вместе, располагаясь в родительской директории. Чтобы посмотреть список зависимостей проекта/ов, необходимо выполнить команду « mvn dependency:tree » : $ cd project $ mvn dependency:tree [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Reactor Build Order: [INFO] [INFO] Main project [INFO] Chaild project1 [INFO] Chaild project2 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Main project 0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ project --- [INFO] com.example:project:pom:0.0.1 [INFO] +- junit:junit:jar:4.11:test [INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test [INFO] \- log4j:log4j:jar:1.2.17:compile [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Chaild project1 0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ project1 --- [INFO] com.example:project1:jar:0.0.1 [INFO] +- junit:junit:jar:4.11:test [INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test [INFO] \- log4j:log4j:jar:1.2.17:compile [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Chaild project2 0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ project2 --- [INFO] com.example:project2:jar:0.0.1 [INFO] +- junit:junit:jar:4.11:test [INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test [INFO] \- log4j:log4j:jar:1.2.17:compile [INFO] ------------------------------------------------------------------------ Maven сначала выводит в консоль зависимости главного проекта, а потом зависимости для каждого из дочерних проектов. Как видно в примере значения groupId (com.example) и version (0.0.1) дочерних проектов совпадают с родительским. Они теперь необязательны и берутся по умолчанию у parent проекта, хотя можно определить собственные значения для каждого подпроекта. Кроме свойств и зависимостей Многомодульный maven проект Maven позволяет собирать проект из нескольких модулей. Каждый программный модуль включает свой проектный файл pom.xml. Один из проектных pom.xml файлов является корневым. Корневой pom.xml позволяет объединить все модули в единый проект. При этом в корневой проектный файл можно вынести общие для всех модулей свойства. А каждый модульный pom.xml должен включать параметры GAV (groupId, artifactId, version) корневого pom.xml. Общие положения разработки многомодульного maven-приложения рассмотрены на странице Наследование проектов в maven . В данной статье рассмотрим пример сборки многомодульного приложения. В качестве «подопытного» приложения используем пример, представленный на странице Pluggable решение . На выходе данного примера мы должны получить 3 архивных и один исполняемый jar-файлов. Главный исполняемый jar-модуль динамически «при необходимости» загружает остальные архивные jar'ники. Данный «подопытный» пример был использован для «оборачивания» jar'ника в exe-файл с использованием maven-плагина launch4j Описание многомодульного проекта На скриншоте представлена структура проекта pluggable, включающая следующие проектные модули : • hello-plugin1 – динамически загружаемый плагин №1 (hello1.jar); • hello-plugin2 – динамически загружаемый плагин №2 (hello2.jar); • plugin-api – интерфейсы описания плагинов (plugin-api.jar); • plugin-loader – главный исполняемый jar модуль. Дополнительные поддиректории проекта, используемые для размещения jar-модулей : • commons – поддиректория размещения архивного jar-модуля описания интерфейса плагинов; • plugins – поддиректория размещения jar-модулей (плагинов); Главный исполняемый модуль plugin-loader.jar размещается в корневой директории проекта, где размещается и проектный/корневой pom.xml. Файл run.bat можно использовать для старта plugin-loader.jar из консоли в Windows. Примечание : в исходные коды классов внесены изменения, связанные с из размещением в пакетах . В исходном примере все классы располагаются в «корне». Начнем рассмотрение примера с корневого многомодульного pom.xml. Листинг многомодульного корневого pom.xml Корневой pom.xml включает параметры GAV (groupId, artifactId, Version), общую для всех модулей проекта секцию и секцию описания модулей Следует отметить, что порядок включения программных модулей проекта составлен таким образом, что сначала представлены исполняемый модуль plugin-loader.jar и плагины (hello- plugin1.jar, hello-plugin2.jar), после чего следует интерфейсный модуль plugin-api.jar. Если собирать проект по-отдельности, то модуль plugin-api.jar должен быть собран в первую очередь и размещен в репозитории командой «mvn install». В этом случае зависимые модули plugin-loader.jar и плагины (hello-plugin1, hello-plugin2) собрались бы нормально. Ну, а мы в этом примере посмотрим, как поступит Maven в случае, если порядок описания модулей для сборки «нарушен». xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > 4.0.0 ru.pluggable.main pluggable pom 1.0.0 MultiModule application true 1.8 1.8 1.8 UTF-8 plugin-loader hello-plugin1 hello-plugin2 plugin Модуль описания интерфейсов плагинов plugin-api.jar На следующем скриншоте представлена структура проекта plugin-api. Интерфейсные классы Plugin, PluginContext располагаются в пакете «ru.plugin». Листинг pom.xml Проектный pom.xml модуля plugin-api.jar включает GAV-параметры, секцию описания родительского GAV ( ) и секцию сборки = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > 4.0.0 ru.pluggable plugin-api jar 1.0.0 Plugin API ru.pluggable.main pluggable 1.0.0 ${project.artifactId} org.apache.maven.plugins maven-jar-plugin 2.3.1 ${basedir}/../commons Модуль описания плагина hello-plugin1.jar Структура проекта hello-plugin1 представлена на следующем скриншоте. Класс HelloPlugin, расположенный в пакете «ru.plugins», реализует свойства интерфейса Plugin. При инициализации класса в методе init определяется значение контекста PluginContext родительского/вызвавшего объекта. Метод invoke выводит в консоль сообщение и изменяет надпись на кнопке родительского объекта. package ru plugins ; import ru plugin Plugin ; import ru plugin PluginContext ; public class HelloPlugin implements Plugin { private PluginContext pc ; @Override public void invoke () { System out println ( "Hello world. I am a plugin 1" ); pc getButton (). setText ( "Other text 1" ); } @Override public void init ( PluginContext context ) { this pc = context ; } } Листинг pom.xml Проектный pom.xml модуля hello-plugin1.jar включает GAV-параметры, секцию описания родительского GAV ( ), секцию зависимостей ( = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > 4.0.0 ru.plugins hello1 jar 1.0.0 Plugin Hello1 ru.pluggable.main pluggable 1.0.0 ru.pluggable plugin-api 1.0.0 ${project.artifactId} maven-resources-plugin 2.6 copy-resources ${basedir}/target/resources src/main/resources **/*.properties org.apache.maven.plugins maven-jar-plugin 2.3.1 ${basedir}/../plugins Примечание : второй плагин hello-plugin2 структурно ничем не отличается от hello-plugin1. Отличия касаются текста сообщения в консоли, надписи на кнопке и параметров GAV в pom.xml. Проектный pom.xml модуля plugin-loader Проектный pom.xml включает GAV-параметры jar-модуля, секцию описания родительского GAV ( ), секцию зависимостей ( xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > 4.0.0 ru.pluggable.loader plugin-loader jar 1.0.0 Plugin Loader ru.pluggable.main pluggable 1.0.0 ru.pluggable plugin-api 1.0.0 ${project.artifactId} org.apache.maven.plugins maven-jar-plugin 2.3.1 ${basedir}/.. ru.pluggable.loader.Boostrap Сборка проекта Сборка всех проектов выполняется одной командой «mvn package» для корневого pom.xml. Maven сначала просматривает проектные файлы pom.xml всех модулей, определенных в корневом pom.xml, и после этого определяет порядок сборки модулей. Как следует из представленных ниже сообщений, выводимых Maven в консоль, порядок сборки был изменен и первым собирается модуль Plugin API, после чего формируются зависимые от него Plugin Loader, Plugin Hello1, Plugin Hello2. D:\pluggable>mvn package [INFO] Scanning for projects... [INFO] ---------------------------------------------------- [INFO] Reactor Build Order: [INFO] [INFO] MultiModule application [INFO] Plugin API [INFO] Plugin Loader [INFO] Plugin Hello1 [INFO] Plugin Hello2 [INFO] [INFO] ---------------------------------------------------- [INFO] Building MultiModule application 1.0.0 [INFO] ---------------------------------------------------- [INFO] [INFO] ---------------------------------------------------- [INFO] Building Plugin API 1.0.0 [INFO] [INFO] --- maven-resources-plugin:2.6:resources \ (default-resources) @ plugin-api --- [INFO] Using 'UTF-8' encoding to copy filtered \ resources. [INFO] skip non existing resourceDirectory \ D:\pluggable\plugin\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile \ (default-compile) @ plugin-api --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 2 source files to \ D:\pluggable\plugin\target\classes [INFO] [INFO] --- maven-resources-plugin:2.6:testResources \ (default-testResources) @ plugin-api --- [INFO] Not copying test resources [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile \ (default-testCompile) @ plugin-api --- [INFO] Not compiling test sources [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test \ (default-test) @ plugin-api --- [INFO] Tests are skipped. [INFO] [INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) \ @ plugin-api --- [INFO] Building jar: \ D:\pluggable\plugin\..\commons\plugin-api.jar [INFO] [INFO] ---------------------------------------------------- [INFO] Building Plugin Loader 1.0.0 [INFO] ---------------------------------------------------- [INFO] [INFO] [INFO] ---------------------------------------------------- [INFO] Building Plugin Hello1 1.0.0 [INFO] ---------------------------------------------------- [INFO] [INFO] [INFO] ---------------------------------------------------- [INFO] Building Plugin Hello2 1.0.0 [INFO] ---------------------------------------------------- [INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) \ @ hello2 --- [INFO] Building jar: \ D:\pluggable\hello-plugin2\..\plugins\hello2.jar [INFO] ---------------------------------------------------- [INFO] Reactor Summary: [INFO] [INFO] MultiModule application ...... SUCCESS [ 0.006 s] [INFO] Plugin API ................... SUCCESS [ 1.957 s] [INFO] Plugin Loader ................ SUCCESS [ 0.391 s] [INFO] Plugin Hello1 ................ SUCCESS [ 0.183 s] [INFO] Plugin Hello2 ................ SUCCESS [ 0.115 s] [INFO] ---------------------------------------------------- [INFO] BUILD SUCCESS [INFO] ---------------------------------------------------- [INFO] Total time: 2.802 s [INFO] Finished at: 2019-06-05T11:07:45+03:00 [INFO] Final Memory: 18M/199M [INFO] ---------------------------------------------------- Примечание : 1. При первой сборке проекта maven не нашел в репозитории модуль plugin-api.jar, прекратил сборку и вывел соответствующее сообщение. После размещения модуля plugin-api.jar в локальном репозитории командой «mvn install» сборка всего проекта прошла успешно. 2. После первой сборки проекта из локального репозитория был удален модуль plugin-api.jar. При дальнейших запусках сборки проекта Maven больше не ругался и сборка проходила нормально. Каким образом Maven собирает проект при отсутствии в локальном репозитории зависимого plugin-api.jar для меня осталось загадкой Maven репозиторий внутри проекта При поиске зависимостей maven последовательно просматривает ряд репозиториев, начиная с локального, расположенного по умолчанию в директории ${user.home}/.m2/repository. Если зависимость в локальном репозитории отсутствует, то далее maven выполняет поиск во внутреннем «корпоративном» репозитории (если он используется), и после этого в центральном репозитории. Как только зависимость найдена, то maven закачивает ее в локальный репозиторий. Задачу maven'у можно «облегчить» размещением репозитория внутри проекта. Только после этого необходимо в проектном файле pom.xml указать местоположение репозитория. Создание maven репозитория в проекте Для создания в проекте maven репозитория необходимо выполнить команду mvn install:install-file. Создадим в корне проекта ${basedir} директорию repo, которую будем использовать в качестве проектного репозитория. Чтобы maven загрузил «зависимость» в repo, необходимо использовать опцию localRepositoryPath. Maven команды для создания репозитория будут выглядеть следующим образом. mvn install : install - file - Dfile = org eclipse swt win32 win32 x86_3 7.1 v3738a jar - DgroupId = org eclipse swt win32 win32 x86 - DartifactId = org eclipse swt win32 win32 x86 - Dversion = 3.7 1.v3738 - Dpackaging = jar - DlocalRepositoryPath = repo - DgeneratePom = true mvn install : install - file - Dfile = org eclipse core runtime_3 7.0 v20110110 jar - DgroupId = org eclipse core runtime - DartifactId = org eclipse core runtime - Dversion = 3.7 0.v20110110 - Dpackaging = jar - DlocalRepositoryPath = repo - DgeneratePom = true mvn install : install - file - Dfile = org eclipse core commands_3 6.0 I20110111 - 0800.jar - DgroupId = org eclipse core commands - DartifactId = org eclipse core commands - Dversion = 3.6 0.I20110111 - 0800 - Dpackaging = jar - DlocalRepositoryPath = repo - DgeneratePom = true После выполнения данных команд в поддиректории проекта repo будет создан проектный репозиторий. Необходимо сказать, что maven команды должны быть однострочные. Здесь на сайте каждая опция представлена отдельной строкой только для наглядности. При выполнении команды «mvn install:install-file» maven выведет в консоль информацию приблизительно следующего содержания : [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------ [INFO] Building swit 1.0 [INFO] ------------------------------------------------------------------ [INFO] [INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ \ swit-repo --- [INFO] Installing E:\swit-repo\ org.eclipse.core.commands_3.6.0.I20110111-0800.jar to E:\swit-repo\repo\org\eclipse\core\commands\ org.eclipse.core.commands\3.6.0.I20110111-0800\org.eclipse.core. commands-3.6.0.I20110111-0800.jar [INFO] Installing C:\Users\PC\AppData\Local\Temp\ mvninstall5195949622522809983.pom to E:\swit-repo\repo\org\eclipse\core\commands\ org.eclipse.core.commands\3.6.0.I20110111-0800\org.eclipse.core. commands-3.6.0.I20110111-0800.pom [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.953 s [INFO] Finished at: 2016-10-16T16:33:30+04:00 [INFO] Final Memory: 5M/15M [INFO] ------------------------------------------------------------------------ Подключение репозитория Для подключения репозитория необходимо в проектном файле pom.xml резместить следующий код : repo true ignore false file://${basedir}/repo Теперь при первой загрузке зависимости из проектного репозитория в локальный maven выведет в консоль приблизительно следующую информацию : E:\swit-repo>mvn clean package -Dmaven.test.skip=true [INFO] Scanning for projects... [INFO] [INFO] ---------------------------------------------------------------- [INFO] Building swit 1.0 [INFO] ---------------------------------------------------------------- Downloading: file://E:/swit-repo/repo/org/eclipse/core/runtime/ org.eclipse.core.runtime/3.7.0.v20110110/ org.eclipse.core.runtime-3.7.0.v20110110.pom Downloaded: file://E:/swit-repo/repo/org/eclipse/core/runtime/ org.eclipse.core.runtime/3.7.0.v20110110/ org.eclipse.core.runtime-3.7.0.v20110110.pom (502 B at 9.8 KB/sec) Downloading: file://E:/swit-repo/repo/org/eclipse/core/commands/ org.eclipse.core.commands/3.6.0.I20110111-0800/ org.eclipse.core.commands-3.6.0.I20110111-0800.pom Downloaded: file://E:/swit-repo/repo/org/eclipse/core/commands/ org.eclipse.core.commands/3.6.0.I20110111-0800/ org.eclipse.core.commands-3.6.0.I20110111-0800.pom (509 B at 16.6 KB/sec) Downloading: file://E:/swit-repo/repo/org/eclipse/equinox/common/ org.eclipse.equinox.common/3.6.0.v20110523/ org.eclipse.equinox.common-3.6.0.v20110523.pom Downloaded: file://E:/swit-repo/repo/org/eclipse/equinox/common/ org.eclipse.equinox.common/3.6.0.v20110523/ org.eclipse.equinox.common-3.6.0.v20110523.pom (506 B at 24.7 KB/sec) Создание exe-файла из jar Пользователям Windows привычнее использовать исполняемое приложение в виде exe-файла, нежели архивного jar-файла. Разработчики настольных java-приложений могут плагином launch4j не только обернуть исполняемый архивный jar-файл в оболочку exe- файла, но и включить в него иконку, автора, версию. Также данный плагин позволяет определить минимальную версию используемой JRE. В данной статье рассмотрим использование maven-плагина launch4j для получения exe-файла. Описание java-примера В качестве java-примера используем pluggable решение, включающее несколько jar-файлов. На следующем скриншоте представлена структура нашего экспериментального примера. Три файла, выделенные красным прямоугольником и относящиеся к задаче создания исполняемого exe-файла, рассматриваются ниже. Несколько слов о структуре примера. Описание с исходными кодами данного java-примера представлено на странице Pluggable решение . Желающие могут поближе познакомиться с технологией динамической загрузки jar-файлов (классов), открыв страницу с подробным описанием исходников. На «выходе» данного примера получаем главный исполняемый модуль plugin-loader.jar, который использует common/plugin-api.jar для загрузки при необходимости (вызове) плагинов plugins/hello1.jar и plugins/hello2.jar. Графический интерфейс примера, представленный на следующем скриншоте, включает 2 кнопки с надписями 'Plugin1' и 'Plugin2'. При нажатии на одну из кнопок приложение подгружает необходимый плагин, который меняет надпись на кнопке. Сообщения в консоли Динамически загружаемые плагины выводят в консоль дополнительно сообщения. Ниже представлены сообщения от двух плагинов. Hello world. I am a plugin 1 I am a plugin 2 Изменения в исходных кодах Необходимо отметить, что в модули PluginLoader.java и Boostrap.java были внесены изменения. Так в PluginLoader.java добавлена метка JLabel с отображением в интерфейсе версии Java : JLabel label = new JLabel ( "Java version : " + System getProperty ( "java.version" )); label setSize ( 200 , 24 ); frame getContentPane (). add ( label ); В класс Boostrap.java внесены изменения, связанные с чтением классов (*.class) из jar'ника, а не из директории bin, как это представлено в исходных кодах. Если этого не сделать, то придётся с собой ещё «таскать» и директорию bin с class'ами. Листинг класса Boostrap.java В главный класс Boostrap внесены изменения определения url : ниже исходной закомментированной строки размещается код определения url в jar-файле. import java io File ; import java lang reflect Method ; import java net URL ; import java net URLClassLoader ; public class Boostrap { public static void main ( String [] args ) throws Exception { File commonsDir = new File ( "commons" ); File [] entries = commonsDir listFiles (); URL [] urls = new URL [ entries length ]; for ( int i = 0 ; i < entries length ; i ++) urls [ i ] = entries [ i ]. toURI (). toURL (); URLClassLoader loader ; loader = new URLClassLoader ( urls , null ); // URL url = new File("bin").toURI().toURL(); File file = new File ( "." ); String path = "jar:file:/" + file getCanonicalPath (); URL url = new URL ( path + "/plugin-loader.jar!/" ); URLClassLoader appLoader ; appLoader = new URLClassLoader ( new URL []{ url }, loader ); Class > appClass = loader loadClass ( "PluginLoader" ); Object appInstance = appClass newInstance (); Method m = appClass getMethod ( "start" ); m invoke ( appInstance ); } } Оборачивание исполняемого jar в exe-файл Обычно плагин maven.plugins.launch4j включают в проектный pom.xml файл, в котором формируется и исполняемый jar-файл. Поскольку основная цель данной статьи наглядно продемонстрировать возможность оборачивания jar в exe, то уберем из проектного pom.xml все лишнее, что связано с формированием jar-файла. Правильнее сказать создадим такой pom.xml, который и будет решать основную задачу оборачивания jar в exe. Cледующий листинг проектного файла pom.xml решает данную задачу. Сам pom.xml существенно упростился и стал более наглядным. В разделе определяются наименование компании (product.company) и наименование исполняемого файла (exeFileName), а также минимальная версия jdkVersion. Основные настройки плагина определяются в разделе наименование иконки. Следует отметить, что в секции = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > 4.0.0 com.demo plugin-loader jar 1.0.0 plugin-loader 1.8 1.8 1.8 UTF-8 MultiModule PluginLoader PluginLoader ${project.artifactId} com.akathist.maven.plugins.launch4j launch4j-maven-plugin plugin-loader package launch4j |