« Наводим порядок в разработке ПО вместе с maven. Часть 5 | Наводим порядок в разработке ПО вместе с maven. Часть 7 » |
Наводим порядок в разработке ПО вместе с maven. Часть 6
Я продолжаю начатый в прошлой статье рассказ о том, как maven умеет работать с многомодульными проектами. В качестве примера я пытаюсь создать enterprise приложение на java, состоящее трех модулей: business-logic (логика работы приложения), web-interface (пользовательский интерфейс) и, собирающий предыдущие две части в единое целое, модуль application.Обсуждаемый пример демонстрирует парочку полезных приемов, которые пригодятся любому, кто занимается серьезным java-программированием и размышляет над тем стоит ли переходить на maven для ведения проекта и управления его жизненным циклом. Хотя я буду стараться рассказывать об сложных вещах простым языком, однако без общего представления о том, что такое ejb, enterprise, веб-модули, вам будет тяжело. В этом случае советую обратиться к какой-нибудь хорошей книжке по java ee 1.5 (EJB 3 in Action или Enterprise JavaBeans, 3.0). Напомню, что многомодульный проект представляет собой не более чем набор каталогов следующего вида: корневой каталог “testmultimodule”, внутри которого размещается главный pom-файл проекта. Этот pom-файл – просто перечисление списка модулей, образующих проект, и общих настроек плагинов, которые применимы для каждого из модулей. Каждый модуль, в свою очередь, – это подкаталог, внутри которого находится (куда уж без него) pom-файл модуля, с ссылкой на родительский проект. И еще в подкаталоге модуля размещается набор ресурсов приложения (исходный код, текстовые и графические файлы). В прошлый раз я закончил рассказ на том, что показал пример pom-файла для самого проекта и для первого модуля с бизнес-логикой – business-logic. Что касается оставшихся модулей (ejb и ear), то в них нет ничего особенного по сравнению с первым: и так и там мы описываем набор зависимостей, нужных для работы модуля, плюс выполняется настройка плагинов maven (очевидно, что каждый вид модулей нуждается в своем особенном наборе плагинов). Вот как будет выглядеть модуль с веб-интерфейсом:
<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">
<parent>
<artifactId>main</artifactId>
<groupId>${myapp.groupid}</groupId>
<version>${myapp.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>${myapp.groupid}</groupId>
<artifactId>web-interface</artifactId>
<packaging>war</packaging>
<version>${myapp.version}</version>
<name>web interface layer</name>
<dependencies>
<dependency>
<groupId>${myapp.groupid}</groupId>
<artifactId>business-logic</artifactId>
<version>${myapp.version}</version>
<type>ejb</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<targetPath>WEB-INF/css</targetPath>
<directory>../styles</directory>
<includes> <include>**/*.css</include> <includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
Рассказ о создании веб-приложения был бы не полон без рассказа об одной “ну очень страшной” проблеме в мире java-разработки (да и не только в java). Не секрет, что хорошая программа должна быть “покрыта” (проверена) тестами. Написав набор функциональных тестов, мы можем проверить логику работы приложения без “подъема” (запуска, инициализации) всего объема той инфраструктуры, которая будет нужна для production стадии (т.е. когда приложение развертывается на сервере заказчика). Однако, некоторые части приложения требует для своей проверки специфические ресурсы, которые нельзя или запрещено эмулировать (jms, распределенные транзакции т.д.). Т.е. часть проверок корректности нашего кода требует создания самодостаточного ear-приложения и развертывания его на сервере приложений. И почти всегда эта операция, ох, и долгая же. Как вывод, нужно максимально стремиться и разрабатывать и тестировать части, составляющие “большое” приложение, по отдельности. Например, если вы работаете над пользовательским интерфейсом и подгоняете css-стили под шаблон, то верхом глупости было бы выполнять весь рабочий цикл “собрать проект и развернуть его на страшно ресурсоемком и медленном сервере приложений”. Гораздо правильнее было бы отлаживать веб-часть проекта на быстром и легком веб-сервере. Здесь я четко противопоставляю с одной стороны сервера приложений, такие как jboss, glassfish, websphere, weblogic, jonas и веб-сервера (tomcat, jetty). К счастью, maven позволяет на основании информации хранящейся внутри веб-модуля запустить веб-сервер (jetty), который будет обслуживать все html/css/jsp файлы этого модуля. Более того, мы можем так настроить jetty, что она будет постоянно сканировать файлы веб-модуля на предмет их изменений и если это потребуется, то автоматически перезагрузит веб-приложение. Веб-сервер jetty будет скачан и настроен для работы самим maven, а с нашей стороны потребуется только добавить в pom-файл веб-модуля следующие строки конфигурации плагина “maven-war-plugin”:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>9090</port>
</connector>
</connectors>
</configuration>
</plugin>
Теперь для того, чтобы выполнить запуск jetty мы заходим в каталог с веб-модулем и выполняем одну из следующих команд: jetty:run, jetty:run-war, jetty:run-exploded. Отличия между этими командами в том, как они конструируют список каталогов и файлов, составляющих веб-приложение. Так jetty-run собирает веб-приложение из статических ресурсов расположенных внутри каталога /src/main/webapp и скомпилированных классов приложения внутри каталога target/classes (компиляция выполняется автоматически). Кроме того, по упомянутой выше ссылке на странице с описанием плагина вы найдете примеры того, как в веб-приложение включить каталоги, размещенные за пределами веб-модуля. Команда “Jetty:run” наиболее удобна почти во всех случаях, за исключением тех редких ситуаций, когда целевое приложение нуждается в генерации war-архива. Например, ситуация когда вы решили привязать к фазе цикла package (создания war-файла) какие-то особые действия, например, собираете ресурсы не относящихся к самому модулю и упаковываете их внутрь war-файла. Если вы выполните команду “m2 jetty:run-war”, в этом случае перед запуском jetty будет выполнена и компиляция проекта и упаковка его в war-файл, который затем развертывается на веб-сервере jetty. В этом случае, jetty уже не может корректно отслеживать изменения в исходный файлах проекта и вы должны в случае необходимости перезагрузки jetty веб-приложения, изменить либо war-файл, либо pom-файл. Только так jetty может узнать о том, что нужно перекомпиляцию и переупаковку проекта, а затем его перезагрузить (работает медленнее, чем первый вариант). Третий способ запуска jetty с помощью команды “m2 jetty:run-exploded” практически идентичен второму способу: также выполняется компиляция и упаковка проекта, но собранный war-файл перед развертыванием на веб-сервере предварительно распаковывается в каталог target.
Описанный выше сценарий применим не только для простеньких веб-приложений, но и в ситуациях, когда у вас есть ejb-модули, требующие развертывания на настоящем сервере приложений. Тут можно либо использовать легковесные контейнеры ejb такие как openejb, OW2 EasyBeans. Эти микроконтейнеры представляют большую часть функциональности согласно спецификации java ee 5.0, но зато гораздо быстрее, чем их полновесные собратья (jboss, websphere, glassfish). Второй вариант предполагает одновременный запуск двух серверов: один из которых медленный сервер приложений, на котором размещена бизнес-логика приложения в форме ejb-модулей. А вот веб-интерфейс можно разместить и на быстром jetty-сервере. И это правильно: ведь мы сейчас активно меняем веб-интерфейс, те же css-стили, разметку страниц, а, значит, нуждается в быстром цикле “попробовать - посмотреть что получилось”.
Одна из самых “вкусных” вещей связанных с внедрением jetty в maven-проект – это совместное использование maven, jetty и jmeter для автоматизации тестирования кода. Jmeter – это популярный и открытый инструмент, предназначенный для имитации веб-запросов клиентов (количество “клиентов” и правила их поведения) к сайту. Затем полученные результаты могут быть визуализированы в виде таблиц, графиков, так чтобы не только определить работает ли приложение, но узнать насколько быстро “отзывается” каждая из веб-страниц. Весной прошлого года я написал серию статей посвященных тестированию веб-приложений и, в частности, там рассказывалось и об jmeter. В любом случае, если вас заинтересует вопрос интеграции maven и средств тестирования, то посетите следующую страничку http://wiki.apache.org/jakarta-jmeter/JMeterMavenPlugin Там вы найдете подробную инструкцию, как подключить jmeter плагин к maven проекту.
Чтобы полностью закрыть рассказ, посвященный созданию многомодульного java-приложения, остается только привести пример кода для последнего, третьего модуля - application. Файл pom для этого модуля похож почти один в один на pom-файлы для web и ejb модулей. Первое отличие в том, что нужно подключить к модулю как зависимости одновременно web и ejb модули, а значение атрибута packaging для файла проекта установить в “ear”. А второе отличие – это подключение к модулю плагина maven-ear-plugin. Разбираться с настройками плагина, нужно держа одновременно открытым и сайт с документацией по самому плагину (http://maven.apache.org/plugins/maven-ear-plugin/index.html) и сайт с документацией по тому серверу приложений, которое вы используете. Т.к. есть нюансы и в расположении файлов модулей и в генерации специальных конфигурационных файлов (к примеру, weblogic и jboss размещают файлы библиотек в разных каталогах). Вот пример моих настроек плагина для сервера приложений weblogic:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<version>5</version>
<defaultLibBundleDir>APP-INF/lib</defaultLibBundleDir>
<modules>
<ejbModule>
<groupId>${myapp.groupid}</groupId>
<artifactId>business-logic</artifactId>
<bundleFileName>logic.jar</bundleFileName>
</ejbModule>
<webModule>
<groupId>${myapp.groupid}</groupId>
<artifactId>web-interface </artifactId>
<contextRoot>/renamed-context</contextRoot>
</webModule>
</modules>
</configuration>
</plugin>
http://learntechnology.net/content/ejb/maven-ejb3.jsp или http://famvdploeg.com/blog/?p=41
« Наводим порядок в разработке ПО вместе с maven. Часть 5 | Наводим порядок в разработке ПО вместе с maven. Часть 7 » |