- PVSM.RU - https://www.pvsm.ru -
Я не люблю Maven.
О моей пассионарной ненависти к этой штуке можно написать не одну статью, но сегодня я хочу поговорить об одной очень хорошей фиче Мавена — об архетипах. Что это такое можно прочитать в официальной документации [1], в каждом из туторилов по Мавену на Хабре(1 [2], 2 [3], 3 [4]), да и вообще, вы наверняка знаете и сами.
Так вот, архетипы — это круто, и было бы здорово, если бы 1) во многих проектах со стандартной структурой они были. 2) можно было бы их прикрутить к тем, у которых их нет.
Примерно так думал Питер Ледбрук [5], когда смотрел на полное отсутствие архетапов в Ratpack [6]. Тогда и родился проект Lazybones [7] — инструмент генерации проектов.
В этой статье я расскажу вам как 1) Пользоваться Lazybones для генерации проектов, для которых уже созданы шаблоны. 2) Создавать новые шаблоны для любых проектов.
Tут все будет предельно коротко:
lazybones list
(или изучаем репозиторий [10])lazybones info <имя шаблона>
(или читаем readme в packag-e шаблона на Бинтрее)lazybones create <имя шаблона> <версия шаблона> <имя директории в которой создавать>
Всё, спасибо за внимание, все свободны. Хотя нет, сейчас будем делать как раз интересное.
Поскольку вы все, скорее всего, знакомы с мавеновским архетипом #361 (maven-archetype-quickstart [11]), мы сделаем что-то похожее (воссоздав все фичи, мы опустим некоторые повторы).
Мало того, что вы сможете сравнить количество скаченного интернета для создания обоих проектов, вы еще и сможете сравнить сложность создания самого шаблона, ибо процесс создания архетайпа Мавена прекрасно описан вот тут [12].
Чего мы хотим добиться:
groupId
, artifactId
и версиейpackage
и положить его в походящую под package
директорию (тоже самое для теста, но мы не будем, для простоты примера)main
, который будет при запуске фазы теста печатать сообщение, выбранное через интерактивную командную строкуmvn test
>lazybones create lazybones-project lzb-templates
│ build.gradle //скрипт сборки шалбонов │ gradlew //файл запуска скрипта для никсов │ gradlew.bat //файл запуска скрипта для винды │ README.md //файл описывающий этот проект │ ├───gradle //вспомогательная директория для скрипта │ └───templates //пустая директория для наших шаблонов
templates
, создаем в ней под-директорию нашего шаблона, и начинаем ваять. Создаем файл версии. Он называется VERSION
и содержит только версию, например 0.1
>mkdir maven-simple >cd maven simple >echo 0.1 > VERSION
readme.md
, который будет показан после создания проекта.src/main/java
, src/main/resources
. В java
и resources
из них кладем по пустому файлу .retain
├───maven-simple │ │ README.md │ │ VERSION │ │ │ └───src │ └───main │ ├───java │ │ .retain │ │ │ └───resources │ .retain
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>${pkg}.App</mainClass>
<arguments>
<argument>${message}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
ААААА!!!!!!!
Так, взяли себя в руки, смотрим. Обратите внимание на всякие ${...}
. Это то, что мы будем менять на значения, которые нам задаст пользователь во время запуска create
. По сути, это просто маркеры Groovy Templates [13]. Если вы знакомы с Velocity, Freemarker или любым другим обработчиком шаблонов, вам всё будет знакомо. Но об этом позже.
Адовый ад в <build></build>
— это всего лишь запуск main
-а класса App
. Обратите внимание, что нам пока нам неизвестны package
этого класса и параметр, который мы передаем в main
.
App.java
:
package ${pkg};
public class App {
public static void main(String[] args) {
System.out.println(args[0]);
}
}
Тут у нас всего одна переменная — опять-же, package
. Заодно мы видим, что main печатает аргумент. Значит, что во время запуска мавена, в фазе теста, мы ожидаем увидеть сообщение, которое пользователь выберет, опять-же, во время create
.
Итак, теперь мы имеем все директории и шаблоны:
│ App.java │ lazybones.groovy │ pom.xml │ README.md │ VERSION │ └───src └───main ├───java │ .retain │ └───resources .retain
import static org.apache.commons.io.FileUtils.moveFileToDirectory
Map<String,String> props = [:]
//метод ask принимает 2 параметра - сообщение, и значение по умолчанию.
//он показывает сообщение и ждет ввода. Ввод (или значение по умолчанию, если ввод пустой) возвращается.
props.groupId = ask('Выберите groupId [org.example]: ', 'org.example')
props.artifactId = ask('Выберите artifactId [maven-simple]: ', 'maven-simple')
props.version = ask('Выберите версию [1.0-SNAPSHOT]: ', '1.0-SNAPSHOT')
props.pkg = ask("Выберите package для класса [$props.groupId]:", props.groupId)
props.message = ask('Чего печатать в тесте? ', 'Привет, лентяй!')
//метод processTemplates обрабатывает шаблоны, заменяя меаркеры значениями из мапы.
processTemplates 'pom.xml', props
//заменяем точки на слэши
String packageDir = props.pkg.replaceAll(/./, '/')
//переносим исходник в нужную директорию
moveFileToDirectory(new File(targetDir, 'App.java'), new File(targetDir, "src/main/java/$packageDir"), true)
//обрабатываем шаблон
processTemplates 'src/main/java/**/App.java', props
Надеюсь, комментарии достаточно понятно объясняют, что происходит. Единственное, наверное, что нужно добавить, это то, что методы ask()
и processTemplates()
и поле targetDir
попадают в скрипт из класса uk.co.cacoethes.lazybones.LazybonesScript
, который является кастомным супер-классом этого скрипта [14].
>gradlew installTemplateMavenSimple
:packageTemplateMavenSimple
:installTemplateMavenSimple
BUILD SUCCESSFUL
>lazybones create maven-simple 0.1 maven-simple
Creating project from template maven-simple 0.1 in 'maven-simple'
Выберите groupId [org.example]: com.demo
Выберите artifactId [maven-simple]:
Выберите версию [1.0-SNAPSHOT]: 0.1
Выберите package для класса [org.example]:org.simple
Чего печатать в тесте? Привет!
Шаблон а-ля архетайп
---------------------------------
Ты создал Мавеновский проект. Может хватит? Грейлд ждет тебя.
Project created in maven-simple!
Сообщение в конце, приходит, конечно из readme.md
. Обратите внимание, я не указал artifactId
, ожидаю maven-simple
по умолчанию.
Заходим в директорию maven-simple, и любуемся:
│ pom.xml │ README.md │ └───src └───main ├───java │ └───org │ └───simple │ App.java │ └───resources
Открываем pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>maven-simple</artifactId>
<version>0.1</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.simple.App</mainClass>
<arguments>
<argument>Привет!</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Всё как надо. Открываем App.java:
package org.simple;
public class App {
public static void main(String[] args) {
System.out.println(args[0]);
}
}
Тоже порядок. Запускаем Мавен:
>mvn test [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building maven-simple 0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-simple --- [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ maven-simple --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-simple --- [INFO] [INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ maven-simple --- [INFO] No sources to compile [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-simple --- [INFO] No tests to run. [INFO] [INFO] >>> exec-maven-plugin:1.2.1:java (default) @ maven-simple >>> [INFO] [INFO] <<< exec-maven-plugin:1.2.1:java (default) @ maven-simple <<< [INFO] [INFO] --- exec-maven-plugin:1.2.1:java (default) @ maven-simple --- Привет! [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.768s [INFO] Finished at: Fri Apr 04 02:54:57 IDT 2014 [INFO] Final Memory: 7M/304M [INFO] ------------------------------------------------------------------------
Вот и всё. Я надеюсь, вы прониклись простотой и изяществом как создания проектов из шаблонов так и созданием самих шаблонов в Lazybones. Мне кажется, за эти простоту и изящество во многом надо благодaрить Груви.
Автор: jbaruch
Источник [18]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/58392
Ссылки в тексте:
[1] в официальной документации: https://maven.apache.org/guides/introduction/introduction-to-archetypes.html
[2] 1: http://habrahabr.ru/post/77382/
[3] 2: http://habrahabr.ru/post/77333/
[4] 3: http://habrahabr.ru/post/78252/
[5] Питер Ледбрук: http://twitter.com/pledbrook
[6] Ratpack: http://habrahabr.ru/post/190452/
[7] проект Lazybones: https://github.com/pledbrook/lazybones
[8] GVM: http://gvmtool.net/
[9] Bintray: https://bintray.com/pkg/show/general/pledbrook/lazybones-templates/lazybones
[10] репозиторий: https://bintray.com/pledbrook/lazybones-templates
[11] maven-archetype-quickstart: https://maven.apache.org/archetype/maven-archetype-bundles/maven-archetype-quickstart/
[12] вот тут: http://habrahabr.ru/post/111408/
[13] Groovy Templates: http://groovy.codehaus.org/Groovy+Templates
[14] кастомным супер-классом этого скрипта: http://mrhaki.blogspot.co.il/2011/11/groovy-goodness-create-our-own-script.html
[15] task rules: http://www.gradle.org/docs/current/userguide/userguide_single.html#N10F81
[16] 15-го апреля в Казани: http://jugru.timepad.ru/event/114085/
[17] 17-го апреля в Москве: http://jugru.timepad.ru/event/109275/
[18] Источник: http://habrahabr.ru/post/218205/
Нажмите здесь для печати.