« Наводим порядок в разработке ПО вместе с maven. Часть 4 | Наводим порядок в разработке ПО вместе с maven. Часть 6 » |
Наводим порядок в разработке ПО вместе с maven. Часть 5
Я продолжаю рассказ об maven, и о том, как он упрощает разработку программных продуктов, задавая четкий ритм и последовательность шагов, через которые проходит жизненный цикл проекта. В прошлый раз мы завершили рассказ о самой большой и известной части maven – управление зависимостями. Сегодня нас ждет продолжение, и мы поговорим о создании многомодульных проектов.Но перед тем как мы начнем рассматривать методики разделения больших проектов на составляющих их части (модули) следует рассказать о том, как различные известные среды разработки (IDE) поддерживают maven. Я пользуюсь в своей практике java-программиста такой известной ide как intellij idea (http://www.jetbrains.com/). На момент написания статьи самая “свежая” версия idea – это восьмая, которая поставляется вместе с “пачкой” плагинов, среди которых есть и maven-плагин. К примеру, после запуска idea, на первом экране вам будет предложены различные стратегии создания проекта. Среди которых, помимо создания “с нуля” или извлечения проекта из cvs/svn, есть и импорт в idea проекта созданного с помощью maven. Для этого вы на экране приветствия idea выбираете пункт “Create New Project”, затем “Import project from external model” -> “maven”. На появившемся диалоговом окне с настройками импорта maven-проекта (см. рис. 1)
вам нужно только указать месторасположение файла pom.xml, да и отметить checkbox-ы “Create idea modules for aggregate projects” и “Automatically re-import on project opening”. Первая опция важна в случае, когда ваш maven-проект состоит из нескольких модулей (вторая часть этой статьи как раз и посвящена этой теме). Опция “Automatically re-import on project openning” нужна для того, чтобы избежать проблемы синхронизации проекта maven и проекта idea. Т.к. после импорта проекта idea создаст “пачку” собственных файлов описывающих проект (с расширениями ipr, iml, iws) и именно эти файлы будут использоваться idea, для компиляции проекта. Это значит, в файлах ipr, iws, iml будут храниться дубли настроек maven (тот же список зависимостей). А теперь представьте себе, что нужно добавить в проект новую библиотеку. И где вы будете это делать, в idea-проекте или в maven-проекте? Для того, чтобы избежать потенциальной несогласованности проектов, idea может каждый раз при открытии проекта выполнять его синхронизацию с мастер-копией в виде maven-проекта (следовательно, все правки проекта вы будете выполнять только в pom-файле). Еще на диалоговом окне импорта maven-проекта советую обратить внимание на кнопку “Advanced”. После ее нажатия появится диалоговое окно с дополнительными настройками maven. Так вы можете указать путь к установленному у вас на компьютере maven, или изменить путь к каталогу репозитория (по умолчанию он располагается в "с:\Documents and Settings\UserName \.m2\repository"). В любом случае после окончания импорта idea создаст для вас проект, повторяющий структуру maven-модулей, и подключит к проекту все необходимые библиотеки-зависимости. Приятно, что каждая библиотека будет представлена тремя файлами: собственно, jar-файл с самой библиотекой, затем файл с исходными кодами библиотеки и файл документации (javadoc). Завершив импорт проекта, вы получите в свое распоряжение специальное окошко “Maven projects” (см. рис. 2)
из которого вы можете инициировать различные фазы жизненного цикла maven (compile, test, install), также мы можете выполнять запуск целей плагинов. Например, на картинке 2 выделен плагин jetty и его goal (цель) jettu-run. Инициировав эту цель, я “в один клик” запустил веб-сервер jetty и развернул на нем свое веб-приложение. Из “мелких вкусностей” могу упомянуть возможность привязать горячие клавиши (клавиатурные сокращения), которые можно привязать к фазам проекта, можно привязать перезапуск того же веб-сервера как действие после компиляции проекта и многое другое. Помимо intellij idea поддержка maven есть и в eclipse. Так выберите меню “File -> Import->Maven Projects”, затем укажите расположение pom-файла с проектом и, вуаля, eclipse сгенерирует набор файлов для проекта (.settings, .classpath, .project). Так вы получаете в свое распоряжение набор инструментов повторяющих почти один в один те, что были доступны в среде intellij idea. И, хоть мне как человеку, предпочитающему idea, не приятно это говорить, но eclipse представляет очень удобный визуальный редактор pom-файла. Т.е. вы можете не только править xml-код “ручками” но и просматривать различные аспекты maven-проекта и редактировать их в графической форме, к примеру я показал на рис.3
как выглядит окно с основными настройками проекта (название группы артефактов, название артефакта-проекта, его версия). А на рис. 4 показано дерево зависимостей артефактов, т.е. от каких артефактов наш проект зависит напрямую, а какие артефакты были разрешены для нашего проекта через поиск транзитивных зависимостей. В прошлой статье, я рассказывал о таком maven-плагине как dependency и его цели dependency:tree, формировавшей на экране “дерево” зависимостей артефактов, т.е. какой артефакт “потянул” какой артефакт и так далее. Это же дерево, но в более красивой, графической форме вы можете увидеть на рис. 4.
Некоторым недостатком (хотя это как посмотреть) поддержки maven в eclipse является “некая недосказанность”, т.е. рассматривать редактор pom-файла как средство быстрого изучения maven не стоит. И предварительно придется проштудировать “мануал” с основной терминологией maven и тем, что она означает. Специально, чтобы закрыть тему про maven и среды разработки я покажу то, как можно выполнить генерацию проекта для idea или для eclipse, что называется “вручную”. Генерацию проекта выполняет команда: “m2 idea:idea” или “m2 eclipse:eclipse”. Но мало вызвать плагин - нужно еще его правильно настроить. C основами настройки плагинов мы уже сталкивались ранее, во второй статье серии, когда я рассказывал о жизненном цикле проекта и плагинах, привязанных к фазам этого цикла. Maven позволяет по аналогии настроить и плагины, которые не участвуют непосредственно в жизненном цикле проекта, например, плагин idea и eclipse:
<build>
<finalName>myapp</finalName>
<plugins>
<plugin>
<artifactId>maven-idea-plugin</artifactId>
<version>2.3-SNAPSHOT</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<dependenciesAsLibraries>true</dependenciesAsLibraries>
<useFullNames>false</useFullNames>
</configuration>
</plugin>
</plugins>
</build>
До сего момента я упорно отмалчивался о том, как организовать много-модульный проект maven. Т.е. проект, состоящий из нескольких частей, когда та же бизнес-логика должна быть размещена отдельно от веб-модуля, формирующего веб-интерфейс приложения. Формально, мульти-модульный проект - это каталог, внутри которого находится pom-файл, содержимого которого сводится не к перечислению библиотек-зависимостей, а просто содержит перечисление модулей. Каждый из модулей проекта - это еще один подкаталог внутри родительского каталога, содержащий файл pom с описанием места, которое данный модуль занимает среди остальных модулей проект (т.е. того, от каких других модулей он зависит), а также перечня обычных зависимостей библиотек и плагинов. Очевидно, что каждый из модулей имеет собственный набор плагинов, привязанных к определенным фазам жизненного цикла проекта и модуля в его составе. Давайте создадим классический проект ear-приложения из трех модулей: ejb, war, ear. В практике количество модулей всегда больше, чем количество автономных частей приложения. Так модуль вполне может иметь пустой набор исходных кодов или ресурсов, и не содержать ни java-кода, ни html-страниц, ничего. Такой модуль-пустышка ценен тем, что внутри его мы описываем набор библиотек-зависимостей (например, библиотеки нужные для работы hibernate). А затем другой модуль (например, ejb) ссылается на модуль-пустышку и получает в свое распоряжение все зависимости, описанные внутри модуля-библиотеки. Такой подход необходим для того, чтобы избежать дубляжей зависимостей. К примеру, у вас в проекте два модуля ejb и для каждого из них нужна библиотека hibernate. Если вы будете описывать составляющие hibernate зависимости по отдельности в каждом из двух модулей, то очень скоро станет вопрос о поддержании их согласованностей, т.е. одинаковых списков составляющих hibernate артефактов и номеров их версией. Более подробно к вопросу создания модулей-пустышек я вернусь позже. А пока попробуем создать многомодульный проект и начнем с того, что внутри каталога testmultimodule я размещу pom файл проекта следующего вида:
<project 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">
<modelVersion>4.0.0</modelVersion>
<groupId>${myapp.groupid}</groupId>
<artifactId>main</artifactId>
<packaging>pom</packaging>
<version>${myapp.version}</version>
<name>main</name>
<modules>
<module>application</module>
<module>business-logic</module>
<module>web-interface</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
< source > 1.5 < / source > <!-- пробелы добавлены специально из-за особенностей форматирования mediawiki -->
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- Project properties -->
<properties>
<myapp.groupid>test01</myapp.groupid>
<myapp.version>1.0</myapp.version>
<myapp.finalname>${artifactId}-${myapp.version}</myapp.finalname>
</properties>
</project>
<project 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">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>main</artifactId>
<groupId>${myapp.groupid}</groupId>
<version>${myapp.version}</version>
</parent>
<groupId>${myapp.groupid}</groupId>
<artifactId>business-logic</artifactId>
<packaging>ejb</packaging>
<version>${myapp.version}</version>
<name>ejb container</name>
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ejb_3.0_spec</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.6.ga</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<ejbVersion>3.0</ejbVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
« Наводим порядок в разработке ПО вместе с maven. Часть 4 | Наводим порядок в разработке ПО вместе с maven. Часть 6 » |