2012-09-17 229 views
1

我正在与三个maven项目一个RESTful webapp。这是我的行家设置(从一些细节条纹)向后兼容神器版本

客户(第二版):

<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> 

模型(第二版):

<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应用程序(第二版):

<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> 

对于每个版本,我都会更新模型的包名以确保唯一的类名。

类Foo在com.mycompany.app:app-model:1.0

package com.mycompany.app.model.v1; 

public class Foo { 
    private String name; 
} 

类Foo在com.mycompany.app:app-model:2.0

package com.mycompany.app.model.v2; 

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

在第一释放一切正常,因为webapp只依赖于com.mycompany.app:app-model:1.0。 在第二个版本中,maven决定只依赖com.mycompany.app:app-model:2.0。 这是正常的行为,我明白为什么这是正常情况下的好事。 尽管如此。我的Backwords compapility代码(在服务器中)希望使用com.mycompany.app:app-model:1.0中的类,因为在该版本中发布的客户端使用这些类。 而较新的客户端(版本2.0)的代码想要使用com.mycompany.app:app-model:2.0类。

我敢肯定,有一种欺骗maven依赖两种方式,但如何? 通常,当我在这种情况下结束时,闹钟会在我的脑海中出现,而且我的解决问题的方式通常有问题。 但我似乎无法在这里找到另一计算策略,不包括其他的“大”弊端:( IDEES人?

回答

1

问题比Maven的更深。默认情况下,JVM将只加载的一个版本如果您的程序的类路径中有两个版本的com.mycompany.app.model.ModelObject(例如),则当您的某个类请求ModelObject时,类加载器将会出去并加载找到的第一个类

一种方法我见过在公共Web服务中处理的是根据它们的版本对所有类进行命名空间,例如,版本1模型类可以在包com.mycompany.app.model_1和版本2模型类com.mycompany.app.model_2中。 lient)可能最终会在这种情况下编写相当多的代码。

一个简单的方法可能是为每个您想要支持的模型托管一个单独的webapp,并使用基于模型版本的webapp路径。因此,在这种情况下,版本1 webapp可能托管在http://app.mycompany.com/webapp_1/...和版本2 http://app.mycompany.com/webapp_2/...。 (Web服务器使用不同的类加载器为每个Web应用程序,以便webapp_1和webapp_2可以使用不同版本的同一类的。)

(如果你喜欢冒险的感觉,你也可以尝试每个模型版本建立自己的独立的类加载器在一个webapp中,我不知道我是否会推荐。)

+0

谢谢你的回答。我想我需要清理。我的意思是“对于每个版本,我更新模型的包名以确保唯一的类名”就是您所描述的。即Foo类将取决于发行版是com.mycompany.app.model.v1.Foo和com.mycompany.app.model.v2.Foo,因此它们将在它们自己之间是唯一的,并且可以位于相同的类路径中。还有什么想法? –

+0

哎呀,我很抱歉!我错过了那部分。 (脸红)我认为最简单的解决方案可能是每个版本都有不同的工件ID。这将有助于确保您的所有Maven插件都能正确解释依赖关系,并强化了v2不是v1的直接替代品的事实。 – matts

+0

是的,也许这是要走的路。这绝对会让maven更快乐。但另一方面,Maven只是我的建筑工具,不应该指定我设计项目的方式。在我看来,_version_只是处理api演变的正确概念。第三,com.mycompany.app:app-model-v1:1.0似乎有点多余,让我感到困惑。尽管如此,在使用maven方法的时候肯定有一点意义......我会在做出任何决定之前详细阐述@Esko的建议,并感谢您的意见。 –

1

您可以使用Maven Dependency plugin's copy goal将这些工件复制到项目中的目录中。复制同一个工件的多个版本应该可以。虽然它还不能帮助您针对这些不同版本编译代码(您可能需要将其他类路径配置为手写的compiler arguments)。

或者只是更改每个版本的工件ID。

+0

好的。所以这将是“欺骗性的maven”解决方案,正如我所说的,这让我觉得我可能会在这个设计上失败。无论如何,我还没有和maven讨论过,从你的建议开始,尝试了一些其他的插件(一些旧的好东西出现了,比如汇编插件),并提出了一个我认为会好的解决方案。在做这种事情时,我希望保持最低限度,而不是为了维护。容易阅读很容易理解。 :) –

3

所以,回答我自己的问题,这是我想出的。我认为这是相当困难的,而不是过多的开箱即用。

我原本3件文物:

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

最后我介绍一个更假象:

  • 融为一体。 mycompany.app:app-depend

这个仅由工件组成的工作就是将所有发布的模型工件捆绑成一个可靠的工件。要做到这一点我也跟着艾司科的建议,并使用Maven插件:

  • org.apache.maven.plugins:Maven的依赖,插件

的目标是解压。这将所有.class文件放在一个目录下,因为我确保每个模型版本都生成了一个独立包中的类,所以它没有任何覆盖就可以很好地工作。我只包含.class文件并省略了所有其他文件(MANIFEST.MF,pom.xml和pom.properties)

之后,trix很简单。我所要做的只是为工件添加资源,并且由于它不包含任何其他资源,因此它成为了一个新的可靠工件。太好了!

现在,这一切工作,我想要的方式,我宣布新的工件作为依赖于我的webapp的神器,让我访问所有的类模型中的所有版本。另一方面,客户端仍然只需要依赖于模型,因为客户端只对最新的型号版本(在发布时)感兴趣。

我还设法设计web应用程序,以便如果发布版本1的客户端调用web应用程序,他会在模型版本1中得到响应,这是他理解的。与此同时,当第2版的客户拨打webbap时,他会在第2版中得到答复,他明白这一点。这一直是我们的目标,我认为这将推动我的api版本化。

我应该提到的是,Web应用程序有它自己的域模型(不同的,但类似演示模型)所以从域名到演示文稿转换为所有请求正在做。对于发行版1,这两个模型几乎相同,但在发行版2中,域已更改,因此具有(最新)演示文稿。 web应用程序做它最好的域转换到两个演示模型1和2,但模型1可能不具有的所有信息。现在,如果领域模型变化太大,以至于没有任何意义将其转换为演示模型1,我认为现在是停止支持该模型的时候了......

depend maven pom最终看起来像这样(for release 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人!