1

私は 3 つの Maven プロジェクトで RESTful Web アプリケーションに取り組んでいます。これは私のMavenセットアップです(いくつかの詳細からストライプ化されています)

クライアント (第 2 リリース):

<project>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app-client</artifactId>
    <version>2.0</version>
    ...
    <dependency>
        <groupId>com.mycompany.app</groupId>
        <artifactId>app-model</artifactId>
        <version>2.0</version>
    </dependency>
</project>

モデル (2 番目のリリース):

<project>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app-model</artifactId>
    <version>2.0</version>
</project>
...
<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <configuration>
        <generatePackage>com.mycompany.app.model.v2</generatePackage>
    </configuration>
</plugin>

Web アプリケーション (2 番目のリリース):

<project>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app-webapp</artifactId>
    <version>2.0</version>
    ...
    <dependency>
        <groupId>com.mycompany.app</groupId>
        <artifactId>app-model</artifactId>
        <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>com.mycompany.app</groupId>
        <artifactId>app-model</artifactId>
        <version>2.0</version>
    </dependency>
</project>

リリースごとに、モデルのパッケージ名を更新して、クラス名が一意になるようにします。

com.mycompany.app:app-model:1.0 のクラス Foo

package com.mycompany.app.model.v1;

public class Foo {
    private String name;
}

com.mycompany.app:app-model:2.0 のクラス Foo

package com.mycompany.app.model.v2;

public class Foo {
    private String name;
    private int age;
}

最初のリリースでは、webapp は com.mycompany.app:app-model:1.0 のみに依存するため、すべてが機能します。2 番目のリリースでは、maven は com.mycompany.app:app-model:2.0 のみに依存することを決定します。これは正常な動作であり、通常のケースでこれが良いことである理由を理解しています。それにもかかわらず。そのリリースでリリースされたクライアントはこれらのクラスを使用するため、(サーバー内の) Backwords 互換性コードは com.mycompany.app:app-model:1.0 のクラスを使用したいと考えています。また、新しいクライアント (バージョン 2.0) のコードでは、com.mycompany.app:app-model:2.0 クラスを使用する必要があります。

両方に依存するようにmavenをだます方法があると確信していますが、どのように?通常、このような状況に陥ると、頭の中でアラームが鳴り、問題を解決する方法に問題があることがよくあります。しかし、他の「より大きな」欠点を含まない別のアプローチをここで見つけることができないようです:(誰かアイデアはありますか?

4

3 に答える 3

3

それで、私自身の質問に答えるために、これは私が思いついたものです。私はそれがかなり前向きであり、すぐに使えるものではないと思います。

もともと私は3つの遺物を持っていました:

  • com.mycompany.app:app-client
  • com.mycompany.app:app-model
  • com.mycompany.app:app-webapp

私はもう1つのアーティファクトを紹介することになりました:

  • com.mycompany.app:app-depend

このアーティファクトのみの仕事は、リリースされたすべてのモデルアーティカクトを1つの信頼できるアーティファクトにバンドルすることです。これを行うために、私はEskoの提案に従い、Mavenプラグインを使用しました。

  • org.apache.maven.plugins:maven-dependency-plugin

開梱することが目標です。これにより、すべての.classファイルがターゲットの下の1つのディレクトリに配置され、すべてのモデルリリースで生成されたクラスが一意のパッケージになっていることを確認したため、上書きなしで正常に機能しました。.classファイルのみを含め、他のすべて(MANIFEST.MF、pom.xml、pom.properties)を省略しました

その後、トリックスは単純でした。アーティファクトにリソースを追加するだけで、他のソースが含まれていないため、新しい信頼できるアーティファクトになりました。良い!

これで、これらすべてが希望どおりに機能するように、新しいアーティファクトをWebアプリケーションアーティファクトの依存関係として宣言し、モデルのすべてのバージョンのすべてのクラスにアクセスできるようにしました。一方、クライアントは最新のモデルバージョン(リリース時)にのみ関心があるため、モデルに依存するだけで済みます。

また、リリース1のクライアントがWebアプリを呼び出した場合に、モデルバージョン1で応答を受け取るように、Webアプリケーションを設計することもできます。これは彼が理解していることです。同時に、リリース2のクライアントがwebbapを呼び出すと、モデルバージョン2で応答を受け取ります。これは彼が理解していることです。これはずっと目標でした、そしてこれは私のapiのバージョン管理を促進すると思います。

Webアプリには独自のドメインモデル(別個ですがプレゼンテーションモデルに類似)があるため、すべてのリクエストに対してドメインからプレゼンテーションへの変換が行われていることに注意してください。リリース1の場合、2つのモデルはほとんど同じですが、リリース2ではドメインが変更されており、(最新の)プレゼンテーションも変更されています。Webアプリケーションは、ドメインをプレゼンテーションモデル1と2の両方に変換するのが最善ですが、モデル1にはすべての情報が含まれていない可能性があります。ドメインモデルが大幅に変更されて、プレゼンテーションモデル1に変換しようとしても意味がない場合は、そのモデルのサポートを停止する時期だと思います...

依存するMavenPomは、最終的に次のようになりました(リリース2の場合)

<project>

  <groupId>com.mycompany.app</groupId>
  <artifactId>app-depend</artifactId>
  <version>2.0</version>
  <packaging>jar</packaging>

  <build>
    <resources>
      <resource>
        <!-- this is where 'unpack' puts the files -->
        <directory>${project.build.directory}/dependency</directory>
        <filtering>false</filtering>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.5.1</version>
        <executions>
          <execution>
            <id>unpack</id>
            <!-- we must do the 'unpack' before the building the jar -->
            <phase>generate-sources</phase>
            <goals>
              <goal>unpack</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>com.mycompany.app</groupId>
                  <artifactId>app-model</artifactId>
                  <version>1.0</version>
                  <type>jar</type>
                  <includes>com/mycompany/app/model/v1/**</includes>
                </artifactItem>
                <artifactItem>
                  <groupId>com.mycompany.app</groupId>
                  <artifactId>app-model</artifactId>
                  <version>2.0</version>
                  <type>jar</type>
                  <includes>com/mycompany/app/model/v2/**</includes>
                </artifactItem>
                <!-- future releases will go here -->
              </artifactItems>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>

それはIT関係者です!

于 2012-09-19T01:19:42.777 に答える
1

Maven Dependencyプラグインのコピー目標を使用して、これらのアーティファクトをプロジェクトのディレクトリーにコピーできます。同じアーティファクトの複数のバージョンをコピーしても問題ありません。これらの異なるバージョンに対してコードをコンパイルすることにはまだ役立ちませんが(追加のクラスパスを手書きのコンパイラー引数として構成する必要がある場合があります)。

または、バージョンごとにアーティファクトIDを変更するだけです。

于 2012-09-18T07:54:49.317 に答える
1

問題は Maven よりも深刻です。デフォルトでは、JVM はクラスの 1 つのバージョンのみをロードします。com.mycompany.app.model.ModelObject(たとえば)の 2 つのバージョンがプログラムのクラスパスにある場合、クラスの 1 つが を要求するModelObjectと、クラスローダは外に出て、最初に見つかったものをロードします。

これがパブリック Web サービスで処理されるのを私が見た 1 つの方法は、バージョンに基づいてすべてのクラスに名前を付けることです。たとえば、バージョン 1 のモデル クラスをパッケージcom.mycompany.app.model_1に入れ、バージョン 2 のモデル クラスを に入れることができますcom.mycompany.app.model_2。ただし、この場合、あなた (およびクライアント) はかなりの余分なコードを書くことになるかもしれません。

おそらく、より簡単な方法は、モデルのバージョンに基づく webapp パスを使用して、サポートするモデルのバージョンごとに個別の webapp をホストすることです。したがって、この場合、バージョン 1 の webapp は でホストされhttp://app.mycompany.com/webapp_1/...、バージョン 2 は でホストされる可能性がありますhttp://app.mycompany.com/webapp_2/...。(Web サーバーは Web アプリケーションごとに個別のクラスローダーを使用するため、webapp_1 と webapp_2 は同じクラスの異なるバージョンを使用できます。)

(冒険したい場合は、単一の webapp 内のモデル バージョンごとに独自の個別のクラスローダーを設定することもできます。ただし、それをお勧めするかどうかはわかりません。)

于 2012-09-17T14:41:48.283 に答える