Пусть для примера есть некий проекта типа "Carbon Application Project", с 1 дочерним проектом типа "ESB Config Project", содержащим некоторое число endpoint`ов и прокси-сервисов. Структура проектов следующая:
MyCarProject
|- pom.xml
|- MyEsbConfigProject
|- pom.xml
|- src
|- main
|- synapse-config
|- endpoints
|- MyEndpoint.xml
|- proxy-services
|- sequences
Хочется, чтобы проект можно было собирать командой:
mvn clean package
вместо того, чтобы делать это через Carbon Studio.
Более того, есть желание использовать в xml-ках ESB-артифактов переменные, которые будут заменяться некоторыми значениями при сборке (например, будут подставляться реальные URL`ы в endoint`ы). Например, чтобы такой endpoint:
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="MyEndpoint">при сборке превращался в:
<address format="soap11"
statistics="disable"
trace="disable"
uri="${endpoint.MyEndpoint.url}">
...
</address>
</endpoint>
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="MyEndpoint">путем задание URL`а в параметре сборки:
<address format="soap11"
statistics="disable"
trace="disable"
uri="http://real.url">
...
</address>
</endpoint>
mvn clean package -Dendpoint.MyEndpoint.url=http://real.url
Если просто выполнить "mvn clean package" в папке проекта Carbon Application Project, сборка завалится с ошибкой. Связана она с тем, что pom-ка проекта Carbon имеет зависимости от артифактов, создаваемых при сборке дочернего проекта ESB Config. Однако, т.к. Carbon Application Project никак не связан с дочерним проектом ESB Config, сборка первого не приводит к предварительной сборке последнего, что и приводит к невозможности разрешить зависимости.
Решается эта проблема созданием модульного проекта, родительского по отношению к первым двум (Carbon Application Project и ESB Config):
MyCarProjectRoot
|- pom.xml
|- MyCarProject
|- pom.xml
|- MyEsbConfigProject
|- pom.xml
|- src
|- main
|- synapse-config
|- endpoints
|- MyEndpoint.xml
|- proxy-services
|- sequences
Содержимое родительской 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.group</groupId>
<artifactId>MyCarProjectRoot</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>MyCarProjectRoot</name>
<modules>
<module>MyCarProject/MyEsbConfigProject</module>
<module>MyCarProject</module>
</modules>
</project>
Теперь, если выполнить mvn clean install для корневой pom-ки, сначала произойдет сборка и установка проекта MyEsbConfigProject, а затем, уже успешно, проекта MyCarProject, на выходе которого мы получим заветный car-ник.
Сборка работает, но с ней не всё идеально. Во-первых, pom-ка проекта ESB Config устроена очень хитро. Она сначала запускает плагины wso2-esb-proxy-plugin / wso2-esb-endpoint-plugin и др. для генерации pom-ки для сборки esb-артифактов (сгенерированная pom-ка помещается в ${project.build.directory}), после чего с помощью exec-maven-plugin запускает mvn для сборки этих сгенерированных pom-ок. Все бы ничего, но только при использовании exec-maven-plugin дочерние mvn-процессы не получают параметров, переданных родительскому mvn. Например, если родительскому mvn был передан путь к специфичному settings.xml, который нужно использовать при сборке, дочерние mvn знать о нем не будут (это особенно критично при сборке на build-сервере, когда зачастую разные сборки используют свои settings.xml). Выход их ситуации - замена exec-maven-plugin на maven-invoker-plugin, т.е. вместо:
<plugin>в pom-ку нужно поместить:
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version>
<extensions>true</extensions>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>mvn</executable>
<workingDirectory>${project.build.directory}</workingDirectory>
<arguments>
<argument>clean</argument>
<argument>install</argument>
<argument>-Dmaven.test.skip=${maven.test.skip}</argument>
</arguments>
</configuration>
</execution>
</executions>
<configuration />
</plugin>
<!-- Replaces exec-maven-plugin plugin, used in origin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<version>1.8</version>
<configuration>
<debug>true</debug>
<pom>${project.build.directory}/pom.xml</pom>
<goals>
<goal>clean</goal>
<goal>install</goal>
</goals>
<properties>
<maven.test.skip>${maven.test.skip}</maven.test.skip>
</properties>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Эффект будет тот же, но дочерние сборки будут сохранять параметры родительской.
Теперь насчет фильтрации xml-ек esb-артифактов. Во-первых, в pom-ке проекта ESB Config необходимо настроить maven-resources-plugin, добавив:
<!-- Filter ESB artifacts -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<outputDirectory>${project.build.directory}/../capp.filtered</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}</directory>
<filtering>true</filtering>
</resource>
</resources>
<includeEmptyDirs>true</includeEmptyDirs>
<escapeWindowsPaths>false</escapeWindowsPaths>
</configuration>
<executions>
<execution>
<id>filter-esb-artifacts</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
</execution>
</executions>
</plugin>
Теперь на фазе package (после того, как была сгенерирована pom-ка для сборки артефактов а сами артефакты были перемещены в ${project.build.directory}) содержимое ${project.build.directory} копируется в директорию ${project.build.directory}/../capp.filtered с выполнением фильтрации. Теперь нужно настроить maven-invoker-plugin на эту директорию:
<!-- Replaces exec-maven-plugin plugin, used in origin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<version>1.8</version>
<configuration>
<debug>true</debug>
<pom>${project.build.directory}/../capp.filtered/pom.xml</pom>
...
</configuration>
...
</plugin>
Также, чтобы директория capp.filtered чистилась при выполнении clean, нужно добавить соотв. настройки в maven-clean-plugin:
<!-- Clean settings to clean capp.filtered directiry -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<configuration>
<filesets>
<fileset>
<directory>${project.build.directory}/../capp.filtered</directory>
</fileset>
</filesets>
</configuration>
</plugin>
Также, на данный момент properties, устанавливаемые при сборке корневого проекта, не подхватываются сборкой проекта ESB Config. Причина в том, что хотя коревой проект и ссылается на проект ESB Config как на дочерний, обратная связь не установлена. Чтобы её установить, нужно добавить в pom-ку проекта ESB Config следующее:
<parent>
<groupId>ru.project.integration.xxx</groupId>
<artifactId>MyCarProjectRoot</artifactId>
<version>1.0.0</version>
<relativePath>../../</relativePath>
</parent>
Всё, теперь можно задавать свойства при сборке корневого проекта, и они будут использоваться при фильтрации xml-конфигураций esb-артефактов.
При сборке более сложных carbon-проектов возникают и другие сложности. Например, при закатывании в car-ник java-библиотек (дочерних проектов типа "Java Library Project") сборка непосредственно мавеном генерирует manifest-файлы, не дающие полученному osgi-бандлу установиться на wso2. Проблема связана с тем, что в Import-Package манифеста включаются все без исключения классы, импортируемые внутри библиотеки, и при установке бандла wso2 ругается на недоступность некоторых из них (чтобы увидеть эту ошибку, пришлось изрядно повозиться: http://barbitoff.blogspot.ru/2013/04/wso2-esb-error-defaultappdeployer-error.html). Если же car-ник собирать из Carbon Studio, в получаемом манифесте блока Import-Package вообще нет.
Исправляется эта проблема внесением соотв. настройки в pom-ку проекта Java Library Project, а именно:
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>my.group</groupId>
<artifactId>my-lib</artifactId>
<version>4.4.0</version>
<packaging>bundle</packaging>
<name>my-lib</name>
<description>my-lib</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.4</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>my-lib</Bundle-SymbolicName>
<Bundle-Name>my-lib</Bundle-Name>
<Export-Package>my.package.*</Export-Package>
<DynamicImport-Package>*</DynamicImport-Package>
<Import-Package></Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
Также, если библиотека содержит не только классы, но и ресурсы, Carbon Studio почему-то не включает их пакеты в pom-ку проекта в блок Export-Package настройки плагина maven-bundle-plugin. Соответственно, при сборке в бандл ресурсы не попадают. Лечится проблема добавлением нужных пакетов в Export-Package.
В общем заморочек много, но имхо они того стоят. Во-первых, такой проект можно собрать, не имея Eclipse и Carbon Studio. Во-вторых, он может вообще собираться автоматически на build-сервере, а благодаря maven-car-deploy-plugin - еще и деплоиться прямо оттуда автоматом на wso2 (благо за счет фильтрации мы можем настроить сборку на нужные url'ы / папки, используемые vfs-транспортом / др. прямо во время сборки). Правда, с деплоем уже не все так радостно. Например, для передеплоивания car-ников, содержащих бандлы, зачастую необходим рестарт шины, а тут уже одним maven-car-deploy-plugin не обойдешься.
Hi Barbitoff
ОтветитьУдалитьI need your help running a assembly build using Maven. I was unsuccessful doing it. Can you help? if so please email me b4babu@gmail.com
Thank you.