День добрый всем. Решил написать заметку о небольших средствах автоматизации, которые возникли в процессе моей работы со связкой Ant+Tomcat. Работаю java-разработчиком, с недавних пор пришлось окунуться в web-разработку на Java (надо сказать не без удовольствия). Никогда с серьезными проектами для web на java не сталкивался, игрался пару раз с примерами в рамках книжек по java из серии «обо всем по немного», но ничего серьезного. А здесь проект из полноценного портала с backend`ом для отвественных за контент, большими объемами данных в БД. Ну что же столкнулся да и столкнулся. Работа пошла, новая область знаний — интересно, мелочи не достают. Но со временем процесс сборки и развертывания приложения стал очень сильно доставать, так как в самые «жаркие» дни приходилось выполнять эту операцию раз по 40, чтобы посмотреть результат работы и прощелкать его. Вот тут и возник вопрос, нельзя ли это как то автоматизировать.
Для тех кто так же как и я раньше не особо представляет процесс сборки и развертывания web-приложений на Java распишу чуток подробнее.
1. Итак, приложение необходимо собрать. Это можно сделать и через IDE, но на больших проектах, где несколько разработчиков и у каждого может быть свой IDE лучше использовать ANT — универсально и удобно. Итак делаем сборку, например так: ant jar. У меня сборка одного модуля jar в нашем проекте в среднем занимает секунд 15-20. Само web-приложение представляет собой war-файл (аналог jar файла в Java SE). Но конечный war-файл может иметь (и как правило имеет) несколько зависимостей от jar-файлов других модулей. Соотвественно, если изменился код модуля, от которого зависит конечный war-файл, то сначала пересобираем модуль, потом собираем само приложение. У нас таких модулей 2, как правило в процессе работы изменения идут в пределах одного модуля, хотя бывает, что необходимо пересобрать оба модуля или ничего не надо пересобирать (кроме конечного war, в коде которого что-то изменилось). В общем, как правило пересобирается 1 модуль. Поэтому последовательность команд такая будет:
В итоге получим war-файл приложения. На сборку с учетом переключений между директориями уходит 50-60 секунд. Сразу скажу, что в проекте конечных war-файлов два: публичная часть и закрытая часть, и для общей сборки есть само собой своя команда, но ее неудобство в том, что происходит сборка «ненужного» сейчас war — что тоже время.
2. Для того, чтобы увидеть само приложение в деле, полученный war-файл необходимо развернуть на сервере. Для этого через браузер заходим в панель управления Tomcat, удаляем старую версию приложения (если оно было), указываем расположение нового war-файла и ждем некоторое время (40-60 секунд), после этого можем начинать «щупать» созданное приложение.
Я не зря пишу примерное время сборки и развертывания приложения — в сумме эти два на первый взгляд простых шага занимают 2-3 минуты. Вроде немного, но при частых изменениях или поиске решения какого-то бага приходится снова и снова пересобирать проект, делать undeploy (удаление) старой версии приложения с сервера, а потом deploy (развертывание) новой версии приложения. Бывает что за день повторяешь эту операцию считанные разы, а бывает, как писал выше, повторы этой операции происходят десятками раз. В итоге само собой возник вопрос об оптимизации данного процесса, т.к. повтор этой операции 10-20 раз ведет к затратам в 30-60 минут. Ладно б если в это время можно было отвлечься от компьютера, а получается, что необходимо плотное участие человека.
Сначала возникла идея в ant добавить одну команду для выполнения шага №1 (отдельно по каждому war), но потом возник вопрос «можно ли автоматизировать шаг №2?», то есть научить ant управлять развертыванием приложения на tomcat. Немного поискав в гугле, нашел несколько решений из которых собрал свое, взяв из каждого какие то моменты.
Процесс сборки приложения в ant я опущу, так как это описано в любом справочном материале по этой утилите, к тому же это специфично для каждого отдельного проекта. Сразу перейду к решению шага №2.
Прежде всего необходимо узнать есть ли в системе tomcat, чтобы было с чем работать:
Создаем задачу «if-has-tomcat», суть которой в том, чтобы проверить доступность директории указанной в системной переменной CATALINA_HOME и результат этой проверки представить в виде переменной «has.tomcat». Выражение
Теперь когда мы знаем, что tomcat есть в системе, можно подключать его библиотеки, которые позволят управлять tomcat из ant. Заодно здесь же проверим, есть ли старая версия war-файла на сервере.
Сначала объявляем необходимые переменные для работы с tomcat: домашнюю папку tomcat, URL tomcat, URL менеджера, логин и пароль. Затем создаем условие, которое проверяет, размещено ли уже приложение (то есть перед тем разворачивать новую версию приложения необходимо будет старую удалить). Здесь ${ant.project.name} содержит название приложения, которое объявляется выше (я объявил в шапке скрипта ant, т.к. эта переменная участвует в тасках по сборке проекта). Следующий шаг — подключение библиотек, которые позволят управлять сервером через ant. Ну и последнее — объявляем таски для ant для управления tomcat.
Теперь когда мы знаем все исходные данные, можно удалять старую версию war-файла (если она есть) — команда undeploy и разворачивать новый war-файл — команда deploy.
Здесь по большому счету ничего сложно. Всегда используются команда ant deploy, которая выполняет очистку всех папок с class файлами (clean), потом выполняется сборка war-файла(war), потом выполняется проверка наличия tomcat (if-has-tomcat), затем при положительном исходе предыдущей проверки выполняется таска undeploy, которая проверяет наличие старой версии war-файла на сервере и при необходимости удаляет его, ну и в последнюю очередь выполняется непосредственно развертывание приложения на сервере. Свойство war в таске deploy, как раз указывает где расположен новый war файл.
В таске undeploy, как видно так же, как и в deploy выполняется проверка на наличие tomcat в системе. Сделано это для того, чтобы можно было безопасно выполнять команду ant undeploy.
В итоге, получилось, что все выполняется одной командой — ant deploy. Дальше можно на 1-2 минуты отвлечься — ant сделает все сам. Чисто время сборки и развертывания осталось тем же, а вот экономия в этом проекте на «ручном» щелканьи и вбивании нескольких команд составила 1-1,5 минуты с каждого deploy. Что за день выходит в 20-30 лишних минут и что самое главное: deploy выполняется с помощью одной команды и не требует к себе внимания, то есть во время сборки и развертывания можно слегка отвлечься и расслабиться.
Для тех кто так же как и я раньше не особо представляет процесс сборки и развертывания web-приложений на Java распишу чуток подробнее.
1. Итак, приложение необходимо собрать. Это можно сделать и через IDE, но на больших проектах, где несколько разработчиков и у каждого может быть свой IDE лучше использовать ANT — универсально и удобно. Итак делаем сборку, например так: ant jar. У меня сборка одного модуля jar в нашем проекте в среднем занимает секунд 15-20. Само web-приложение представляет собой war-файл (аналог jar файла в Java SE). Но конечный war-файл может иметь (и как правило имеет) несколько зависимостей от jar-файлов других модулей. Соотвественно, если изменился код модуля, от которого зависит конечный war-файл, то сначала пересобираем модуль, потом собираем само приложение. У нас таких модулей 2, как правило в процессе работы изменения идут в пределах одного модуля, хотя бывает, что необходимо пересобрать оба модуля или ничего не надо пересобирать (кроме конечного war, в коде которого что-то изменилось). В общем, как правило пересобирается 1 модуль. Поэтому последовательность команд такая будет:
cd {директория модуля}
ant jar
cd {директория конечного приложения}
ant war
В итоге получим war-файл приложения. На сборку с учетом переключений между директориями уходит 50-60 секунд. Сразу скажу, что в проекте конечных war-файлов два: публичная часть и закрытая часть, и для общей сборки есть само собой своя команда, но ее неудобство в том, что происходит сборка «ненужного» сейчас war — что тоже время.
2. Для того, чтобы увидеть само приложение в деле, полученный war-файл необходимо развернуть на сервере. Для этого через браузер заходим в панель управления Tomcat, удаляем старую версию приложения (если оно было), указываем расположение нового war-файла и ждем некоторое время (40-60 секунд), после этого можем начинать «щупать» созданное приложение.
Я не зря пишу примерное время сборки и развертывания приложения — в сумме эти два на первый взгляд простых шага занимают 2-3 минуты. Вроде немного, но при частых изменениях или поиске решения какого-то бага приходится снова и снова пересобирать проект, делать undeploy (удаление) старой версии приложения с сервера, а потом deploy (развертывание) новой версии приложения. Бывает что за день повторяешь эту операцию считанные разы, а бывает, как писал выше, повторы этой операции происходят десятками раз. В итоге само собой возник вопрос об оптимизации данного процесса, т.к. повтор этой операции 10-20 раз ведет к затратам в 30-60 минут. Ладно б если в это время можно было отвлечься от компьютера, а получается, что необходимо плотное участие человека.
Сначала возникла идея в ant добавить одну команду для выполнения шага №1 (отдельно по каждому war), но потом возник вопрос «можно ли автоматизировать шаг №2?», то есть научить ant управлять развертыванием приложения на tomcat. Немного поискав в гугле, нашел несколько решений из которых собрал свое, взяв из каждого какие то моменты.
Процесс сборки приложения в ant я опущу, так как это описано в любом справочном материале по этой утилите, к тому же это специфично для каждого отдельного проекта. Сразу перейду к решению шага №2.
Прежде всего необходимо узнать есть ли в системе tomcat, чтобы было с чем работать:
<target name="if-has-tomcat">
<property environment="env"/>
<condition property="has.tomcat">
<available file="${env.CATALINA_HOME}"/>
</condition>
</target>
Создаем задачу «if-has-tomcat», суть которой в том, чтобы проверить доступность директории указанной в системной переменной CATALINA_HOME и результат этой проверки представить в виде переменной «has.tomcat». Выражение
property environment="env"
как раз позволяет получить доступ к системным переменным.Теперь когда мы знаем, что tomcat есть в системе, можно подключать его библиотеки, которые позволят управлять tomcat из ant. Заодно здесь же проверим, есть ли старая версия war-файла на сервере.
<target name="check-if-deployed" depends="if-has-tomcat" if="has.tomcat">
<property name="tomcat.home.dir" location="${env.CATALINA_HOME}" />
<property name="tomcat.base.url" value="http://localhost:8080" />
<property name="tomcat.manager.url" value="${tomcat.base.url}/manager/text" />
<property name="tomcat.user.name" value="login" />
<property name="tomcat.user.password" value="password" />
<condition property="is.webapp.deployed">
<http url="${tomcat.base.url}/${ant.project.name}" />
</condition>
<path id="tomcat.classpath">
<!-- We need the Catalina jars for Tomcat -->
<fileset dir="${tomcat.home.dir}/lib">
<include name="catalina-ant.jar"/>
<include name="tomcat-coyote.jar"/>
<include name="tomcat-util.jar"/>
</fileset>
<fileset dir="${tomcat.home.dir}/bin">
<include name="tomcat-juli.jar"/>
</fileset>
</path>
<!-- Configure the custom Ant tasks for the Manager application -->
<taskdef name="deploy" classname="org.apache.catalina.ant.DeployTask" classpathref="tomcat.classpath"/>
<taskdef name="list" classname="org.apache.catalina.ant.ListTask" classpathref="tomcat.classpath"/>
<taskdef name="reload" classname="org.apache.catalina.ant.ReloadTask" classpathref="tomcat.classpath"/>
<taskdef name="findleaks" classname="org.apache.catalina.ant.FindLeaksTask" classpathref="tomcat.classpath"/>
<taskdef name="resources" classname="org.apache.catalina.ant.ResourcesTask" classpathref="tomcat.classpath"/>
<taskdef name="start" classname="org.apache.catalina.ant.StartTask" classpathref="tomcat.classpath"/>
<taskdef name="stop" classname="org.apache.catalina.ant.StopTask" classpathref="tomcat.classpath"/>
<taskdef name="undeploy" classname="org.apache.catalina.ant.UndeployTask" classpathref="tomcat.classpath"/>
</target>
Сначала объявляем необходимые переменные для работы с tomcat: домашнюю папку tomcat, URL tomcat, URL менеджера, логин и пароль. Затем создаем условие, которое проверяет, размещено ли уже приложение (то есть перед тем разворачивать новую версию приложения необходимо будет старую удалить). Здесь ${ant.project.name} содержит название приложения, которое объявляется выше (я объявил в шапке скрипта ant, т.к. эта переменная участвует в тасках по сборке проекта). Следующий шаг — подключение библиотек, которые позволят управлять сервером через ant. Ну и последнее — объявляем таски для ant для управления tomcat.
Теперь когда мы знаем все исходные данные, можно удалять старую версию war-файла (если она есть) — команда undeploy и разворачивать новый war-файл — команда deploy.
<target name="undeploy" depends="if-has-tomcat, check-if-deployed" if="is.webapp.deployed">
<!-- TOMCAT undeploy-->
<undeploy
url="${tomcat.manager.url}"
username="${tomcat.user.name}"
password="${tomcat.user.password}"
path="/${ant.project.name}"
/>
</target>
<target name="deploy" depends="clean, war, if-has-tomcat, undeploy" if="has.tomcat">
<!-- TOMCAT deploy-->
<deploy
url="${tomcat.manager.url}"
username="${tomcat.user.name}"
password="${tomcat.user.password}"
path="/${ant.project.name}"
war="${dist.dir}/${ant.project.name}.war"
/>
</target>
Здесь по большому счету ничего сложно. Всегда используются команда ant deploy, которая выполняет очистку всех папок с class файлами (clean), потом выполняется сборка war-файла(war), потом выполняется проверка наличия tomcat (if-has-tomcat), затем при положительном исходе предыдущей проверки выполняется таска undeploy, которая проверяет наличие старой версии war-файла на сервере и при необходимости удаляет его, ну и в последнюю очередь выполняется непосредственно развертывание приложения на сервере. Свойство war в таске deploy, как раз указывает где расположен новый war файл.
В таске undeploy, как видно так же, как и в deploy выполняется проверка на наличие tomcat в системе. Сделано это для того, чтобы можно было безопасно выполнять команду ant undeploy.
В итоге, получилось, что все выполняется одной командой — ant deploy. Дальше можно на 1-2 минуты отвлечься — ant сделает все сам. Чисто время сборки и развертывания осталось тем же, а вот экономия в этом проекте на «ручном» щелканьи и вбивании нескольких команд составила 1-1,5 минуты с каждого deploy. Что за день выходит в 20-30 лишних минут и что самое главное: deploy выполняется с помощью одной команды и не требует к себе внимания, то есть во время сборки и развертывания можно слегка отвлечься и расслабиться.