2015-03-07 7 views
0

У меня есть требование поддерживать несколько типов клиентских сборок, используя один и тот же родительский файл pom. Задача для меня заключается в том, что разные клиенты будут использовать несколько разные библиотеки. Например, один клиент может использовать SQL-сервер, а другой может использовать MySQL. Это простой пример, но другие библиотеки могут включать те, которые могут потребовать лицензии, которую мы бы не имели внутри, но наш клиент имел бы. Не исключая их внутренне, это может привести к тому, что mavens начнут битовое построение, поскольку библиотеки не будут присутствовать в нашем репозитории. Моя первоначальная идея состояла в том, чтобы создать профиль в нашем родительском pom для каждого клиента, а затем определить любые зависимости, которые используются только для этого клиента в этих профилях. Эти профили активируются либо отсутствием свойства, либо имуществом, имеющим определенное значение. У меня возникла проблема с тем, как зависимости решаются при использовании нескольких модулей, особенно когда один ребенок зависит от другого. Я считаю, что суть вопроса вращается вокруг переменной, запускающего профиля не установлена ​​в каком-то момент в процессе разрешения, но позвольте мне, например, с помощью простого примера:Включает ли активация профиля 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/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>com.test</groupId> 
    <artifactId>parent</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <packaging>pom</packaging> 

    <modules> 
    <module>../child-a</module> 
    <module>../child-b</module> 
    </modules> 

<profiles> 
    <profile> 
     <id>client-a</id> 
     <activation> 
      <property> 
       <name>!clientbuild</name> 
      </property> 
     </activation> 
     <dependencies> 
      <dependency> 
       <groupId>com.microsoft.sqlserver</groupId> 
       <artifactId>sqljdbc4</artifactId> 
       <version>4.0</version> 
      </dependency> 
     </dependencies> 
    </profile> 
    <profile> 
     <id>client-b</id> 
     <activation> 
      <property> 
       <name>clientbuild</name> 
       <value>clientb</value> 
      </property> 
     </activation> 
     <dependencies> 
      <dependency> 
       <groupId>mysql</groupId> 
       <artifactId>mysql-connector-java</artifactId> 
       <version>5.1.34</version> 
      </dependency> 
     </dependencies> 
    </profile> 
    </profiles> 
</project> 

Я определил профили client-a и client-b в моем родительском pom. Клиент-профиль должен быть активирован в отсутствие свойства «clientbuild», и профиль «client-b» должен быть активирован, если для свойства «clientbuild» установлено значение «clientb». Если я запускаю зависимость: дерево от родителей и указать «clientb» в моем файле Maven пользователя «setting.xml», я получаю следующее:

--- maven-dependency-plugin:2.8:tree (default-cli) @ parent --- 
com.test:parent:pom:0.0.1-SNAPSHOT 
\- mysql:mysql-connector-java:jar:5.1.34:compile 

--- maven-dependency-plugin:2.8:tree (default-cli) @ child-a --- 
com.test:child-a:jar:0.0.1-SNAPSHOT 
\- mysql:mysql-connector-java:jar:5.1.34:compile 

--- maven-dependency-plugin:2.8:tree (default-cli) @ child-b --- 
com.test:child-b:jar:0.0.1-SNAPSHOT 
+- com.test:child-a:jar:0.0.1-SNAPSHOT:compile 
| \- com.microsoft.sqlserver:sqljdbc4:jar:4.0:compile 
\- mysql:mysql-connector-java:jar:5.1.34:compile 

«родитель» и «ребенок-а» проекты имеют правильные зависимости , но «child-b» имеет зависимости от обоих профилей. Из дерева я вижу, что неверная зависимость включена, потому что maven считает, что «child-a» имеет зависимость от sqljdbc. Я убежден, что при создании maven подбирает «child-a» и разрешает его зависимости от родительского pom без использования свойства «clientbuild», которое я установил в файле maven «settings.xml». Есть ли способ заставить maven использовать свойство clientbuild в течение всего процесса разрешения зависимостей?

В ходе различных экспериментов я решил, что если я должен удалить «! Clientbuild» и заменить его проверкой на определенное значение (а затем указать это значение в моих настройках.xml), или если у меня нет требования активации и вручную запускать профили с -PI, получить желаемые результаты. К сожалению, мы не можем поручить, чтобы наш первый клиент использовал -P или указывал любые другие аргументы во время процесса сборки, поэтому использование отсутствия свойства clientbuild является единственной проверкой активации, которую я могу использовать в настоящее время для «client-a». Кроме того, если я заменю эту проверку на «activeByDefault», я получаю то же поведение, что и выше, добавляя «clientb» в качестве свойства в файл «settings.xml».

Итак, учитывая все это, мой вопрос: я пытаюсь сделать это даже возможно? Я знаю, что мои требования довольно необычны. В идеале я бы хотел, чтобы профиль всегда указывался во время сборки, но, к сожалению, это невозможно для нашего клиента.

Вкратце, мне нужно активировать профиль по умолчанию, который содержит определенные зависимости, но эти зависимости будут заменены другим набором зависимостей из другого профиля, если он активирован свойством. Кроме того, это должно работать, когда некоторые модули, принадлежащие одному и тому же родителю, зависят друг от друга, как показано выше. У кого-нибудь есть опыт с этим или есть какие-то альтернативные методы, которые я могу попробовать?

В качестве заключительной сноски я использую Eclipse (в частности, Spring Tool Suite) и встроенный Maven 3, который поставляется вместе с ним.

Edit (ребенок РОМ и settings.xml): В соответствии с просьбой, вот РОМ для ребенка-а и ребенка-б. Я также включил свой файл user settings.xml, который у меня есть, когда я пытаюсь применить свойство clientbuild как «clientb».

ребенок-а 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> 
    <parent> 
    <groupId>com.test</groupId> 
    <artifactId>parent</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    </parent> 
    <artifactId>child-a</artifactId> 
    <packaging>jar</packaging> 
</project> 

ребенок-б 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> 
    <parent> 
    <groupId>com.test</groupId> 
    <artifactId>parent</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    </parent> 
    <artifactId>child-b</artifactId> 
    <packaging>jar</packaging> 

    <dependencies> 
    <dependency> 
     <groupId>com.test</groupId> 
     <artifactId>child-a</artifactId> 
     <version>${project.version}</version> 
    </dependency> 
    </dependencies> 
</project> 

settings.xml когда clientb свойство "clientbuild" активен:

<?xml version="1.0" encoding="UTF-8"?> 
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> 

    <pluginGroups> 
    </pluginGroups> 

    <proxies> 
    </proxies> 

    <servers> 
    </servers> 

    <mirrors> 
    </mirrors> 

    <profiles> 
    <profile> 
    <id>client-profile</id> 
    <activation> 
     <activeByDefault>true</activeByDefault> 
    </activation> 
    <properties> 
     <clientbuild>clientb</clientbuild> 
    </properties> 
    </profile> 
    </profiles> 
</settings> 

Я также попытался установить тег, чтобы активировать профиль «client-build» в моем файле settings.xml вместо использования тега activeByDefault, но это дало те же результаты.

Редактирование 2 (пояснение отношения и использование параметра JVM): Чтобы уточнить, профили client-a/client-b не влияют на взаимосвязь между модулями child-a/child-b. Связь, независимо от профиля, заключается в том, что child-b зависит от child-a. Единственное, что влияет на профиль client-a/client-b, - это добавить sqljdbc или mysql-connector-java в качестве зависимости от родителя.

Что касается переменной clientbuild, используемой в командной строке. Передача -Dclientbuild = clientb приведет к желаемому дереву зависимостей.

--- maven-dependency-plugin:2.8:tree (default-cli) @ parent --- 
com.test:parent:pom:0.0.1-SNAPSHOT 
\- mysql:mysql-connector-java:jar:5.1.34:compile 

--- maven-dependency-plugin:2.8:tree (default-cli) @ child-a --- 
com.test:child-a:jar:0.0.1-SNAPSHOT 
\- mysql:mysql-connector-java:jar:5.1.34:compile 

--- maven-dependency-plugin:2.8:tree (default-cli) @ child-b --- 
com.test:child-b:jar:0.0.1-SNAPSHOT 
+- com.test:child-a:jar:0.0.1-SNAPSHOT:compile 
\- mysql:mysql-connector-java:jar:5.1.34:compile 

Однако причина, почему я хочу/нужно использовать settings.xml вместо этого, потому что с помощью аргумента командной строки, при закреплении ручной сборки Maven, не фиксирует тот факт, что встроенный Maven Eclipse, будет по-прежнему разрешить зависимостей, как показано выше в исходной зависимости: выход дерева (child-b будет иметь зависимости обоих профилей, а не только профиль client-b). Это само по себе может быть приемлемым (хотя поведение не так, как ожидалось), однако у нас нет некоторых зависимостей внутри активируемого профиля, который не должен быть (от клиента - профиля) из-за лицензирования и других причины. Если присутствуют зависимости обоих профилей, это приведет к многим отсутствующим ошибкам артефакта в Eclipse.

+0

Не могли бы вы добавить дескрипторы для модулей child-a и b? – tmarwen

+0

@tmarwen Я добавил pOMs для child-a и child-b, а также мой файл settings.xml, который использует Eclipse, когда я пытаюсь активировать профиль «client-b», используя свойство «clientbuild». – Eluamous

+0

Я не уверен, что полностью понимаю связь между модулями child-a/child-b и профилями client-a/client-b. Если child-a должен быть только модулем, когда клиент-профиль активен, тогда вы должны перенести объявление модуля в профиль и переместить зависимости в модули. Если это не так, не могли бы вы проверить, получилось ли такое же поведение, когда переменная clientbuild указана непосредственно в командной строке (-Dclientbuild = clientb), а не в файле settings.xml? Спросите, потому что ваша установка выглядит хорошо для меня в целом. – kaqqao

ответ

1

Я обнаружил следующее:

  1. ребенок-б был активируя правильный профиль от родителя, используя свойство, установленное в settings.xml

  2. ребенок-а не наследуя это свойство во время разрешения зависимостей child-b и, таким образом, активирует неправильный профиль в результате. Я не могу полностью объяснить, почему свойство не было унаследовано, но единственным объяснением, которое я могу думать, является то, что свойство применяется только к строимому проекту, а не к его зависимостям. Я не уверен, что чувствую, что это должно быть поведение, но это то, что я наблюдал.

TLDR

Для того, чтобы обойти выше того, что я в конечном итоге делает садилось все зависимости в пределах двух профилей в качестве дополнительного использования: верно.Поскольку один из побочных эффектов/функций опционального отключает транзитивность, любой данный проект, который строится (в данном случае - дочерний-b), активирует правильный профиль, но любые другие зависимости проекта с одним и тем же родителем не будут наследовать неправильные зависимости. Обратите внимание, что неправильный профиль для child-a все равно будет активирован, поэтому, если у вас есть другие теги в профиле (например, плагины или что-то еще), они все равно будут неправильно активированы. Это не было проблемой в моем случае использования, потому что в профиле содержались только зависимости.

Смежные вопросы