Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Пишем плагин для Maven

Anna | 3.06.2014 | нет комментариев
Есть у меня на некоторых maven-планах профиль, с поддержкой которого производится копирование shared-библиотек с дальнейшим перезапуском сервера Tomcat.

Maven profile

<profile>
	<id>deploy-deps</id>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<useSubDirectoryPerScope>true</useSubDirectoryPerScope>
							<excludeGroupIds>исключаем некоторые группы, попадающие в war-архив</excludeGroupIds>
						</configuration>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<executions>
					<execution>
						<id>05-stop-tomcat</id>
						<phase>package</phase>
						<goals>
							<goal>exec</goal>
						</goals>
						<configuration>
							<arguments>
								<argument>-ssh</argument>
								<argument>-4</argument>
								<argument>-agent</argument>
								<argument>-i</argument>
								<argument>${putty.key}</argument>
								<argument>${ssh.user}@${ssh.host}</argument>
								<argument>${tomcat.dir.root}/bin/shutdown.sh</argument>
							</arguments>
							<executable>plink</executable>
						</configuration>
					</execution>
					<execution>
						<id>10-clean-shared-jars</id>
						<phase>package</phase>
						<goals>
							<goal>exec</goal>
						</goals>
						<configuration>
							<arguments>
								<argument>-ssh</argument>
								<argument>-4</argument>
								<argument>-agent</argument>
								<argument>-i</argument>
								<argument>${putty.key}</argument>
								<argument>${ssh.user}@${ssh.host}</argument>
								<argument>rm</argument>
								<argument>-Rf</argument>
								<argument>${tomcat.dir.shared}/*.jar</argument>
							</arguments>
							<executable>plink</executable>
						</configuration>
					</execution>
					<execution>
						<id>15-upload-shared-jars</id>
						<phase>package</phase>
						<goals>
							<goal>exec</goal>
						</goals>
						<configuration>
							<arguments>
								<argument>-scp</argument>
								<argument>-4</argument>
								<argument>-agent</argument>
								<argument>-i</argument>
								<argument>${putty.key}</argument>
								<argument>${project.build.directory}/dependency/compile/*.jar</argument>
								<argument>${ssh.user}@${ssh.host}:${tomcat.lib.shared}/</argument>
							</arguments>
							<executable>pscp</executable>
						</configuration>
					</execution>
					<execution>
						<id>20-start-tomcat</id>
						<phase>package</phase>
						<goals>
							<goal>exec</goal>
						</goals>
						<configuration>
							<arguments>
								<argument>-ssh</argument>
								<argument>-4</argument>
								<argument>-agent</argument>
								<argument>-i</argument>
								<argument>"${putty.key}"</argument>
								<argument>${ssh.user}@${ssh.host}</argument>
								<argument>bin/startup.sh</argument>
							</arguments>
							<executable>plink</executable>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</profile>
отходя в сторону, поведаю для чего сей профиль

В части планов применяется связка Nginx Tomcat. Для данной связки реализовано следующее:

  1. Для каждого неподвижного контента применяется некоторый каталог за пределами webapps. В данный каталог «глядит» Nginx и отдаёт по web-пути “/static/*”
  2. Все shared java-библиотеки (редко изменяемые) грузятся в каталог ${catalina.home}/shared, и в Tomcat в файле conf/catalina.properties настроена для этого переменная «shared.loader»
  3. Для всякого инстанса Tomcat сделан свой системный пользователь
  4. Для доступа по SSH применяются ключи и у всякого разработчика он свой

Соответственно, загрузка неподвижного контента и shared-библиотек это отдельные профили. Всё остальное собирается в war-архив и устанавливается через типовой web-manager Tomcat-а.
А Дабы не плодить конфигураций, применяется PAgent, в тот, что теснее и добавленые надобные нам private keys. Они же применяются для подключения через Putty

Лежит себе профиль в pom.xml, не кусается как бы бы, даже пашет помаленьку на благо программера, но вот только есть в нём пара «минусов» — занимает много места при развёрнутом pom.xml да ещё и в новые планы доводится вставлять.
И если от второго минуса дозволено избавиться написав образец в любимая_IDE либо свой архетип наваять, то от первого минуса не так-то легко избавить.

Верно ли не так легко? может «обернём» данный профиль в виде плагина для Maven? Сказано, сделано.

Шаг 1. Создаём заготовку плана для плагина maven

, в котором указываем тип сборки «maven-plugin». Так же нам потребуются зависимости:
1) org.apache.maven.plugin-tools:maven-plugin-annotations для вероятности указания Mojo классов не через JavaDoc, а с поддержкой аннотаций
2) org.twdata.maven:mojo-executor для вероятности запуска других плагинов из нашего.
Пока зависимостей довольно — пора приступать собственно к реализации самого Mojo класса.
commit

Шаг 2. Пишем Mojo-класс

Заготовка класса

@Mojo(name = "deploy-deps", defaultPhase = LifecyclePhase.PROCESS_SOURCES, threadSafe = true)
public class DeployDepsMojo extends AbstractMojo {

	@Component
	protected MavenProject                      mavenProject;
	@Component
	protected MavenSession                      mavenSession;
	@Component
	protected BuildPluginManager                pluginManager;
	protected MojoExecutor.ExecutionEnvironment _pluginEnv;

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		_pluginEnv = executionEnvironment(mavenProject, mavenSession, pluginManager);
	}
}

commit

Нам понадобится генерация mojo тегов из аннотаций (commit):

Заготовка класса

<build>
	<!-- ... -->
	<plugins>
		<plugin>
			<artifactId>maven-plugin-plugin</artifactId>
			<executions>
				<execution>
					<id>help-goal</id>
					<goals>
						<goal>helpmojo</goal>
					</goals>
				</execution>
				<execution>
					<id>mojo-descriptor</id>
					<goals>
						<goal>descriptor</goal>
					</goals>
				</execution>
			</executions>
			<configuration>
				<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
			</configuration>
		</plugin>
	</plugins>
</build>
Добавляем копирование зависимостей
было

<plugin>
	<artifactId>maven-dependency-plugin</artifactId>
	<executions>
		<execution>
			<phase>package</phase>
			<goals>
				<goal>copy-dependencies</goal>
			</goals>
			<configuration>
				<useSubDirectoryPerScope>true</useSubDirectoryPerScope>
				<excludeGroupIds>исключаем некоторые группы, попадающие в war-архив</excludeGroupIds>
			</configuration>
		</execution>
	</executions>
</plugin>
стало

@Mojo(name = "deploy-deps",
      requiresDependencyResolution = ResolutionScope.TEST,
      defaultPhase = LifecyclePhase.PROCESS_SOURCES, threadSafe = true)
public class DeployDepsMojo extends AbstractMojo {

// ...

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		_pluginEnv = executionEnvironment(mavenProject, mavenSession, pluginManager);
		copyDependencies();
	}

	private void copyDependencies() throws MojoExecutionException {
		// TODO expects corrections https://github.com/TimMoore/mojo-executor/issues/18
		Plugin pluginDependency = plugin("org.apache.maven.plugins", "maven-dependency-plugin", "2.8");

		final Xpp3Dom cfg = configuration(element(name("useSubDirectoryPerScope"), "true"));

		executeMojo(pluginDependency, goal("copy-dependencies"), cfg, _pluginEnv);
	}
}

commit
Коротко:

  1. «requiresDependencyResolution = ResolutionScope.TEST» требуется для приобретения списка зависимостей — без этого плагин maven-dependency-plugin не произведёт их копирование
  2. «threadSafe = true» указывает на то, что данный Mojo дозволено запускать в отдельном потоке — он самодостаточен
  3. статический способ executeMojo разрешает исполнить всякий goal для всякого доступного плагина с изложением конфигурации окружения. В данном случае окружение остаётся тем же (переменная _pluginEnv)
Добавляем способ для остановки сервера Tomcat
было

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>exec-maven-plugin</artifactId>
	<executions>
		<execution>
			<id>05-stop-tomcat</id>
			<phase>package</phase>
			<goals>
				<goal>exec</goal>
			</goals>
			<configuration>
				<arguments>
					<argument>-ssh</argument>
					<argument>-4</argument>
					<argument>-agent</argument>
					<argument>-i</argument>
					<argument>${putty.key}</argument>
					<argument>${ssh.user}@${ssh.host}</argument>
					<argument>${tomcat.dir.root}/bin/shutdown.sh</argument>
				</arguments>
				<executable>plink</executable>
			</configuration>
		</execution>
		<!-- ... -->
	</executions>
</plugin>
стало

public class DeployDepsMojo extends AbstractMojo {
	public static final String  PLG_EXEC_CFG_ARGUMENTS  = "arguments";
	public static final Xpp3Dom PLG_EXEC_CFG_EXEC_PLINK = element(name("executable"), "plink").toDom();
	public static final String  PLG_EXEC_GOAL_EXEC      = goal("exec");
	public static final String  PLG_EXEC_PROTOCOL_SSH   = "-ssh";

	// ...

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		_pluginEnv = executionEnvironment(mavenProject, mavenSession, pluginManager);
		_pluginExec = plugin("org.codehaus.mojo", "exec-maven-plugin", "1.2.1");
		copyDependencies();
		tomcatShutdown();
	}

	private void tomcatShutdown() throws MojoExecutionException {
		Xpp3Dom cfg = getBaseConfigExec(PLG_EXEC_PROTOCOL_SSH);
		final Xpp3Dom arguments = cfg.getChild(PLG_EXEC_CFG_ARGUMENTS);
		arguments.addChild(element(name("argument"), "${ssh.user}@${ssh.host}").toDom());
		arguments.addChild(element(name("argument"), "bin/shutdown.sh").toDom());
		cfg.addChild(PLG_EXEC_CFG_EXEC_PLINK);

		executeMojo(_pluginExec, PLG_EXEC_GOAL_EXEC, cfg, _pluginEnv);
	}

	private Xpp3Dom getBaseConfigExec(String protocol) {
		final Element el0 = element(name("argument"), protocol);
		final Element el1 = element(name("argument"), "-4");
		final Element el2 = element(name("argument"), "-agent");
		final Element el3 = element(name("argument"), "-i");
		final Element el4 = element(name("argument"), "${putty.key}");
		return configuration(element(name(PLG_EXEC_CFG_ARGUMENTS), el0, el1, el2, el3, el4));
	}
}
Добавляем оставшиеся способы

По аналогии с предыдущим пунктом, добавляем способы для удалённой чистки каталога tomcat.lib.shared, копирования в него новых библиотек и дальнейшего запуска сервера Tomcat.
commit

Шаг 3. Устанавливаем плагин в репозитарий и правим конфигурацию Maven-плана

Установка плагина в локальный репозитарий выполняется примитивный командой «mvn clean install»

И правим конфигурацию плана:

было

<profile>
	<id>deploy-deps</id>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<useSubDirectoryPerScope>true</useSubDirectoryPerScope>
							<excludeGroupIds>исключаем некоторые группы, попадающие в war-архив</excludeGroupIds>
						</configuration>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<executions>
					<execution>
						<id>05-stop-tomcat</id>
						<phase>package</phase>
						<goals>
							<goal>exec</goal>
						</goals>
						<configuration>
							<arguments>
								<argument>-ssh</argument>
								<argument>-4</argument>
								<argument>-agent</argument>
								<argument>-i</argument>
								<argument>${putty.key}</argument>
								<argument>${ssh.user}@${ssh.host}</argument>
								<argument>${tomcat.dir.root}/bin/shutdown.sh</argument>
							</arguments>
							<executable>plink</executable>
						</configuration>
					</execution>
					<execution>
						<id>10-clean-shared-jars</id>
						<phase>package</phase>
						<goals>
							<goal>exec</goal>
						</goals>
						<configuration>
							<arguments>
								<argument>-ssh</argument>
								<argument>-4</argument>
								<argument>-agent</argument>
								<argument>-i</argument>
								<argument>${putty.key}</argument>
								<argument>${ssh.user}@${ssh.host}</argument>
								<argument>rm</argument>
								<argument>-Rf</argument>
								<argument>${tomcat.dir.shared}/*.jar</argument>
							</arguments>
							<executable>plink</executable>
						</configuration>
					</execution>
					<execution>
						<id>15-upload-shared-jars</id>
						<phase>package</phase>
						<goals>
							<goal>exec</goal>
						</goals>
						<configuration>
							<arguments>
								<argument>-scp</argument>
								<argument>-4</argument>
								<argument>-agent</argument>
								<argument>-i</argument>
								<argument>${putty.key}</argument>
								<argument>${project.build.directory}/dependency/compile/*.jar</argument>
								<argument>${ssh.user}@${ssh.host}:${tomcat.lib.shared}/</argument>
							</arguments>
							<executable>pscp</executable>
						</configuration>
					</execution>
					<execution>
						<id>20-start-tomcat</id>
						<phase>package</phase>
						<goals>
							<goal>exec</goal>
						</goals>
						<configuration>
							<arguments>
								<argument>-ssh</argument>
								<argument>-4</argument>
								<argument>-agent</argument>
								<argument>-i</argument>
								<argument>"${putty.key}"</argument>
								<argument>${ssh.user}@${ssh.host}</argument>
								<argument>bin/startup.sh</argument>
							</arguments>
							<executable>plink</executable>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</profile>
стало

<profile>
	<id>deploy-deps</id>
	<build>
		<plugins>
			<plugin>
				<groupId>info.alenkov.tools.maven</groupId>
				<artifactId>tomcat7-ewar-plugin</artifactId>
				<executions>
					<execution>
						<phase>process-sources</phase>
						<goals>
							<goal>deploy-deps</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</profile>

На этом процесс совершенствования читабельности maven-плана и выноса Зачастую используемого «наружу» завершен (заключительный commit для этого поста). Впереди ещё оптимизация кода, добавление параметров и многое другое, но это теснее вовсе иная история, которую когда-нибудь поведаю програжителям.

Источник: programmingmaster.ru
Оставить комментарий
БАЗА ЗНАНИЙ
СЛУЧАЙНАЯ СТАТЬЯ
СЛУЧАЙНЫЙ БЛОГ
СЛУЧАЙНЫЙ МОД
СЛУЧАЙНЫЙ СКИН
НОВЫЕ МОДЫ
НОВЫЕ СКИНЫ
НАКОПЛЕННЫЙ ОПЫТ
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB