Is there a way to build a project for different client with the same base but with modularity for some feature that would be discovered at runtime?

huangapple go评论78阅读模式
英文:

Is there a way to build a project for different client with the same base but with modularity for some feature that would be discovered at runtime?

问题

I'm used to using the E4 Eclipse framework to build desktop applications and now I would like to migrate to a simple maven project.

在使用E4 Eclipse框架构建桌面应用程序方面,我已经习惯了,现在我想迁移到一个简单的Maven项目。

In the Eclipse platform with OSGi, there is a notion of bundle, feature and product.

在带有OSGi的Eclipse平台中,有捆绑包(bundle)、特性(feature)和产品(product)的概念。

When I want to build my project for client A, I have a file A.product describing all the dependencies. For client B, I have B.product and so on.

当我想为客户A构建我的项目时,我有一个描述所有依赖关系的A.product文件。对于客户B,我有B.product等等。

Of course, my software shares the same base, but if a client wants a new feature (like a plugin) I have to add it to my product file, and the new feature will be discovered at runtime and present to my software.

当然,我的软件共享相同的基础,但如果客户想要一个新功能(如插件),我必须将它添加到我的产品文件中,新功能将在运行时被发现并呈现给我的软件。

In maven, I don't find a good way to do the same things, because there is only one pom.xml describing the whole project. How can I introduce modularisation for plugin discovered at runtime?

在Maven中,我找不到一个好的方法来做同样的事情,因为只有一个pom.xml描述整个项目。我应该如何引入在运行时发现的插件的模块化?

Should I have multiple POM for each client?

我应该为每个客户使用多个POM吗?

Should I use the profile to do that? I tried but I was not easy to manage.

我应该使用配置文件(profile)来做吗?我尝试过,但不容易管理。

Is there another maven good way to do it, and to manage the variability easily?

是否有另一种更好的Maven方法来做到这一点,并且容易管理可变性?

英文:

I'm used to using the E4 Eclipse framework to build desktop applications and now I would like to migrate to a simple maven project.

In the Eclipse platform with OSGi, there is a notion of bundle, feature and product.

When I want to build my project for client A, I have a file A.product describing all the dependencies. For client B, I have B.product and so on.

Of course, my software shares the same base, but if a client wants a new feature (like a plugin) I have to add it to my product file, and the new feature will be discovered at runtime and present to my software.

In maven, I don't find a good way to do the same things, because there is only one pom.xml describing the whole project. How can I introduce modularisation for plugin discovered at runtime?
Should I have multiple POM for each client?
Should I use the profile to do that? I tried but I was not easy to manage.

Is there another maven good way to do it, and to manage the variability easily?

答案1

得分: 1

以下是您要翻译的内容:

"Re „And (maybe) another Pom.xml (or profile ?)“ in one of your comments to the question:

One of Maven's principles is: one project (declared in a POM), one resulting (main) artifact (JAR, WAR, ...). („main“ since there can be accompanying artifacts like ...-sources.jar, ...-javadoc.jar, ...-jar-with-dependencies.jar, ....zip, ...)

Maven POMs are of declarative nature. That means, there are no (imperative) ifs to skip declarations on occasion and you also can't add/remove declaration (XML) elements during build (you "just" can add/change element text contents via properties). (There are plugins with a <skip>true|false> parameter, which can be set/overridden with a property, but that's not a general rule and therefore there are not many of them.)

Profiles are a way to overcome this no-if-principle. With them you can activate ("inject") declarations which set or override existing declarations at build time via various profile activation methods.

Regarding your comment after removing the <kbd>osgi</kbd> tag, I'm going to update this answer later. In the meantime you can have a look at my answer to Maven: Lifecycle vs. Phase vs. Plugin vs. Goal.

UPDATE

+- jojal-main
   +- pom.xml   ... contains declarations common for all of your projects
   +- base-main
      +- pom.xml   ... contains declarations common for all base projects
      +- A
         +- src/main/java/your/package/Plugin.java
         +- pom.xml
      +- B
         +- src/main/java/your/package/ClassA.java   ... implements Plugin
         +- pom.xml
      +- C
         +- src/main/java/your/package/ClassB.java   ... implements Plugin
         +- pom.xml
   +- product-main
      +- pom.xml   ... contains declarations common for all product projects
      +- product1
         +- src/main/java/your/package/Product1.java   ... references A &amp; B
         + pom.xml
      +- product2
         +- src/main/java/your/package/Product2.java   ... references A &amp; C
         +- pom.xml
      +- product3
         +- src/main/java/your/package/Product3.java  ... references A &amp; B &amp; C
         +- pom.xml

jojal main POM

<project ...>

  <groupId>name.jojal</groupId>
  <artifactId>jojal-main</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>  <!-- different to the default 'jar'[1] -->

  <modules>  <!-- to build projects in sub-dirs at once[2] -->
    <module>base-main</module>
    <module>product-main</module>
  </modules>

  ... declarations common for all of your projects like dependencies for unit testing, logging etc. ..

<project>

[1] POM Reference, Packaging
[2] POM Reference, Aggregation

Base main POM

<project ...>

  <parent>   <!-- declarations are inherited from this parent POM[3] -->
    <groupId>name.jojal</groupId>
    <artifactId>jojal-main</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>jojal-base-main</artifactId>  <!-- <groupId>, <version> can be omitted if the same as in parent -->
  <packaging>pom</packaging>

  <modules>
    <module>A</module>
    <module>B</module>
    <module>C</module>
  </modules>

  ... declarations common for all base projects ...

<project>

[3] POM Reference, Inheritance

A POM

<project ...>

  <parent>
    <groupId>name.jojal.base</groupId>
    <artifactId>jojal-base-main</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
 
  <artifactId>project-a</artifactId>

<project>

B POM

<project ...>

  <parent>
    <groupId>name.jojal.base</groupId>
    <artifactId>jojal-base-main</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>project-b</artifactId>

  <dependencies>
    <dependency>
      <groupId>name.jojal.base</groupId>
      <artifactId>project-a</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>

<project>

C POM

<project ...>

  <parent>
    <groupId>name.jojal.base</groupId>
    <artifactId>jojal-base-main</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
 
  <artifactId>project-c</artifactId>

  <dependencies>
    <dependency>
      <groupId>name.jojal.base</groupId>
      <artifactId>project-a</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>

<project>

Product main POM

<project ...>

  <parent>
    <groupId>name.jojal</groupId>
    <artifactId>jojal-main</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>jojal-product-main</artifactId>
  <packaging>pom</packaging>

  <modules>
    <module>product1</module>
    <module>product2</module>
    <module>product3</module>
  </modules>

  ... declarations common for all product projects ...

<project>

Product 1 POM

<project ...>

  <parent>
    <groupId>name.jojal.product</groupId>
    <artifactId>jojal-product-main</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>product-1</artifactId>

  <dependencies>
    <dependency>
      <groupId>name.jojal.base</groupId>
      <artifactId>project-b</artifactId>  <!-- project-a is resolved automatically by Maven
                                               as a transitive dependency[4] -->
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>

<project>

[4] POM Reference, Dependencies

Product 2 POM

<project ...>

  <parent>
    <groupId>name.j

<details>
<summary>英文:</summary>

Re „_And (maybe) another Pom.xml (or profile ?)_“ in one of your comments to the question:

One of Maven&#39;s principles is: _one_ project (declared in a POM), _one_ resulting (main) artifact ([JAR, WAR, ...][packaging]). („main“ since there can be accompanying artifacts like [`...-sources.jar`, `...-javadoc.jar`][source&amp;doc], [`...-jar-with-dependencies.jar`, `....zip`][assembly], ...)

Maven POMs are of declarative nature. That means, there are no (imperative) `if`s to skip declarations on occasion and you also can&#39;t add/remove declaration (XML) elements during build (you &quot;just&quot; can add/change element text contents via [properties](https://maven.apache.org/pom.html#Properties)). (There are plugins with a `&lt;skip&gt;false|true` parameter, which can be set/overridden with a property, but that&#39;s not a general rule and therefore there are not many of them.)

[Profiles][profiles] are a way to overcome this no-if-principle. With them you can [activate (&quot;inject&quot;) declarations][inject] which set or override existing declarations at build time via [various profile activation methods][activate].

Regarding your comment after removing the &lt;kbd&gt;osgi&lt;/kbd&gt; tag, I&#39;m going to update this answer later. In the meantime you can have a look at my answer to [Maven: Lifecycle vs. Phase vs. Plugin vs. Goal][answer].

## UPDATE ##

+- jojal-main
+- pom.xml ... contains declarations common for all of your projects
+- base-main
+- pom.xml ... contains declarations common for all base projects
+- A
+- src/main/java/your/package/Plugin.java
+- pom.xml
+- B
+- src/main/java/your/package/ClassA.java ... implements Plugin
+- pom.xml
+- C
+- src/main/java/your/package/ClassB.java ... implements Plugin
+- pom.xml
+- product-main
+- pom.xml ... contains declarations common for all product projects
+- product1
+- src/main/java/your/package/Product1.java ... references A & B
+ pom.xml
+- product2
+- src/main/java/your/package/Product2.java ... references A & C
+- pom.xml
+- product3
+- src/main/java/your/package/Product3.java ... references A & B & C
+- pom.xml

### jojal main POM ###
````lang-xml
&lt;project ...&gt;
  ...

  &lt;groupId&gt;name.jojal&lt;/groupId&gt;
  &lt;artifactId&gt;jojal-main&lt;/artifactId&gt;
  &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;packaging&gt;pom&lt;/packaging&gt;  &lt;!-- different to the default &#39;jar&#39;[1] --&gt;

  &lt;modules&gt;  &lt;!-- to build projects in sub-dirs at once[2] --&gt;
    &lt;module&gt;base-main&lt;/module&gt;
    &lt;module&gt;product-main&lt;/module&gt;
  &lt;/modules&gt;

  ... declarations common for all of your projects like dependencies for unit testing, logging etc. ..

&lt;project&gt;

<sup>[1]</sup> POM Reference, Packaging<br />
<sup>[2]</sup> POM Reference, Aggregation

Base main POM

&lt;project ...&gt;
  ...

  &lt;parent&gt;   &lt;!-- declarations are inherited from this parent POM[3] --&gt;
    &lt;groupId&gt;name.jojal&lt;/groupId&gt;
    &lt;artifactId&gt;jojal-main&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;/parent&gt;

  &lt;artifactId&gt;jojal-base-main&lt;/artifactId&gt;  &lt;!-- &lt;groupId&gt;, &lt;version&gt; can be omitted if the same as in parent --&gt;
  &lt;packaging&gt;pom&lt;/packaging&gt;

  &lt;modules&gt;
    &lt;module&gt;A&lt;/module&gt;
    &lt;module&gt;B&lt;/module&gt;
    &lt;module&gt;C&lt;/module&gt;
  &lt;/modules&gt;

  ... declarations common for all base projects ...

&lt;project&gt;

<sup>[3]</sup> POM Reference, Inheritance

A POM

&lt;project ...&gt;
  ...

  &lt;parent&gt;
    &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
    &lt;artifactId&gt;jojal-base-main&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;/parent&gt;
 
  &lt;artifactId&gt;project-a&lt;/artifactId&gt;

&lt;project&gt;

B POM

&lt;project ...&gt;
  ...

  &lt;parent&gt;
    &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
    &lt;artifactId&gt;jojal-base-main&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;/parent&gt;

  &lt;artifactId&gt;project-b&lt;/artifactId&gt;

  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
      &lt;artifactId&gt;project-a&lt;/artifactId&gt;
      &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;

&lt;project&gt;

C POM

&lt;project ...&gt;
  ...

  &lt;parent&gt;
    &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
    &lt;artifactId&gt;jojal-base-main&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;/parent&gt;
 
  &lt;artifactId&gt;project-c&lt;/artifactId&gt;

  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
      &lt;artifactId&gt;project-a&lt;/artifactId&gt;
      &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;

&lt;project&gt;

Product main POM

&lt;project ...&gt;
  ...

  &lt;parent&gt;
    &lt;groupId&gt;name.jojal&lt;/groupId&gt;
    &lt;artifactId&gt;jojal-main&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;/parent&gt;

  &lt;artifactId&gt;jojal-product-main&lt;/artifactId&gt;
  &lt;packaging&gt;pom&lt;/packaging&gt;

  &lt;modules&gt;
    &lt;module&gt;product1&lt;/module&gt;
    &lt;module&gt;product2&lt;/module&gt;
    &lt;module&gt;product3&lt;/module&gt;
  &lt;/modules&gt;

  ... declarations common for all product projects ...

&lt;project&gt;

Product 1 POM

&lt;project ...&gt;
  ...

  &lt;parent&gt;
    &lt;groupId&gt;name.jojal.product&lt;/groupId&gt;
    &lt;artifactId&gt;jojal-product-main&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;/parent&gt;

  &lt;artifactId&gt;product-1&lt;/artifactId&gt;

  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
      &lt;artifactId&gt;project-b&lt;/artifactId&gt;  &lt;!-- project-a is resolved automatically by Maven
                                               as a transitive dependency[4] --&gt;
      &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;

&lt;project&gt;

<sup>[4]</sup> POM Reference, Dependencies

Product 2 POM

&lt;project ...&gt;
  ...

  &lt;parent&gt;
    &lt;groupId&gt;name.jojal.product&lt;/groupId&gt;
    &lt;artifactId&gt;jojal-product-main&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;/parent&gt;

  &lt;artifactId&gt;product-2&lt;/artifactId&gt;

  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
      &lt;artifactId&gt;project-c&lt;/artifactId&gt;
      &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;

&lt;project&gt;

Product 3 POM

&lt;project ...&gt;
  ...

  &lt;parent&gt;
    &lt;groupId&gt;name.jojal.product&lt;/groupId&gt;
    &lt;artifactId&gt;jojal-product-main&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  &lt;/parent&gt;

  &lt;artifactId&gt;product-3&lt;/artifactId&gt;

  &lt;dependencies&gt;

    &lt;dependency&gt;
      &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
      &lt;artifactId&gt;project-b&lt;/artifactId&gt;
      &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
      &lt;groupId&gt;name.jojal.base&lt;/groupId&gt;
      &lt;artifactId&gt;project-c&lt;/artifactId&gt;
      &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;/dependency&gt;

  &lt;/dependencies&gt;

&lt;project&gt;

[Please note: Not tested in real, typos possible]

huangapple
  • 本文由 发表于 2020年8月11日 02:10:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63345741.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定