【问题标题】:Version number in jar name - how to handle persistence.xml?jar 名称中的版本号 - 如何处理 persistence.xml?
【发布时间】:2016-09-14 14:43:51
【问题描述】:

我们正在使用大量 jar 构建 ear-files。其中一些包含定义持久性单元的 persistence.xml 文件,这些持久性单元使用

引用其他 jar
<jar-file>other.jar</jar-file>

现在我们计划在未来使用 Maven,并且 jar 名称现在包含版本号。对于上述机制来说,这是一个巨大的问题:我们需要指定other-1.2.3.jar,而不是other.jar。但是在构建jar时无法知道正确的版本号,因为在ear的构建中,依赖中介可以将other-1.2.3.jar替换为other-2.3.4.jar,这样我在jar的persistence.xml中的引用就会失效。

所以我的问题是:在构建大型 ear 文件时,如何在 Maven 中正确管理 persistence.xml 文件?


编辑:

让我试着构建一个小例子来说明我的观点:

让我们有first-ejb-1.0.0.jar 取决于other-1.2.3.jarsecond-ejb-1.0.0.jar 取决于other-2.3.4.jarfirst-ejb-1.0.0.jarsecond-ejb-1.0.0.jar 都包含一个带有 &lt;jar-file&gt; 条目的 persistence.xml。 first-ejb-1.0.0.jar 指向 other-1.2.3.jarsecond-ejb-1.0.0.jar 指向 other-2.3.4.jar。到目前为止,一切顺利。

现在我从first-ejb-1.0.0.jarsecond-ejb-1.0.0.jar 构建一个耳朵。依赖关系已解决,但耳中只能包含other-*.jar 之一。比如说,我们的依赖中介选择了other-2.3.4.jar。然后first-ejb-1.0.0.jar 有一个死的&lt;jar-file&gt; 条目,指向一个不存在的jar。

【问题讨论】:

  • 1-hint 是“Maven 资源过滤”是做这些事情的标准方式。 2-hint using spring "entityManagerFactory" 具有属性 "packagesToScan" 允许您在包列表中查找实体,因此通过包名称而不是 jar 名称进行引用。
  • @Hishamkh:您能否更具体地谈谈第一个提示?
  • 我认为 other.jar 是您的项目之一。为什么依赖中介决定选择哪个版本? other.jar 不是您项目的直接依赖项吗??
  • 请用 pom 结构更新你打算如何把东西放在一起,这样你可能会得到具体的答案。
  • 问题如下:我建jar的时候,可以指定other.jar的版本,但是别人建ear的时候,里面可能有不同的版本:Maybe, someone else 用 2.3.4 构建了他的 jar,耳朵现在包含了 other.jar 的 2.3.4。问题是persistence.xml是在编译jar时创建的,但在构建ear时会读取它。

标签: java maven jar persistence


【解决方案1】:

maven-ear-plugin 有一个属性fileNameMapping,您可以通过该属性指定文件名映射以用于 EAR 文件中包含的所有依赖项。以下值是有效的standardno-versionfullno-version-for-ejbstandard 表示文件名是 artifactId,包括。工件的版本。 no-version 表示文件只是没有版本的 artifactId。 full 表示文件名为 groupId+artifactId+artifact 的版本。 no-version-for-ejb 表示文件名是 artifactId,如果是 EJB 类型,则没有版本。

所以指定ear插件如下:

  <plugin>
    <artifactId>maven-ear-plugin</artifactId>
    <version>2.10.1</version>
    <configuration>
       <fileNameMapping>no-version</fileNameMapping>
    </configuration>
  </plugin>

可能会为您解决问题。

备选方案 2:外部化 persistence.xml

另一种方法是将persistence.xml 外部化。最直接的方法是创建一个包含 persistence.xml 的 jar 并将其放入 ear 的 lib 文件夹中:

EAR +
    |- lib +
    |      |- core-module.jar
    |      \- persistence-module.jar +
    |                                 \- META-INF +
    |                                              \- persistence.xml
    |- ejb1-module.jar
    \- ejb2-module.jar

EJB 模块可以是 jar 档案或展开的目录。在上述设置中,persistence.xml 看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="my-persistence-unit">
        <!-- Note: it's relative to `persistence-module.jar` file location in EAR -->
        <jar-file>../ejb1-module.jar</jar-file>
        <jar-file>../ejb2-module.jar</jar-file>
        ....
    </persistence-unit>
</persistence>

在 EAR 级别定义的持久性单元通常对应用程序中的所有组件可见。但是,如果同名的持久性单元由 EAR 中的 EJB-JAR、WAR 或应用程序 jar 文件定义,则在 EAR 级别定义的该名称的持久性单元对该 EJB 定义的组件不可见- JAR、WAR 或应用程序 jar 文件,除非持久性单元引用使用持久性单元名称 # 语法来指定路径名以消除引用的歧义。当使用# 语法时,路径名是相对于引用应用程序组件jar 文件的。例如,语法../lib/persistenceUnitRoot.jar#myPersistenceUnit 指的是一个持久化单元,其名称在persistence.xml 文件的name 元素中指定为myPersistenceUnit,并且该持久化单元的根的相对路径名是@987654342 @。

可以通过使用@PersistenceContext(unitName = "../lib/persistenceUnitRoot.jar#myPersistenceUnit")注释entityManager来指定持久化单元。

【讨论】:

  • 谢谢。正如我在@Anton Koscejev 的答案的评论中所说,这是一个有用的解决方法,但我更喜欢文件名中带有版本号的类似 Maven 的解决方案。
  • 你不能使用 maven 过滤并用 &lt;jar-file&gt;other.jar&lt;/jar-file&gt; 代替 &lt;jar-file&gt;other-${other.version}.jar&lt;/jar-file&gt;
  • 正如我在问题中所说:ear build 可能会用同一 jar 的其他版本替换 jar。所以我在构建 jar 期间提供的参考可能不再起作用。
  • 并且不可能有persistence.xml外部(或覆盖在耳朵?)
  • 也许吧。如果以前做过类似事情的人告诉我,那就太好了。
【解决方案2】:

由于您有一个 EAR 项目和一个 Other 项目,我假设您有一个父项目。

我不完全确定你的意思

但是在构建jar时无法知道正确的版本号,因为在ear的构建中,依赖中介可以将other-1.2.3.jar替换为other-2.3.4.jar

我知道 other 在构建 ear 之前不知道它的版本(但为什么?)。 您可以执行以下操作:在父项目中,定义一个变量来保存实际的最终版本。

<properties>
  <my.final.version>...</my.final.version>
</properties>

显然,my.final.version 应该设置为您的实际期望值。 然后,将 persistence.xml 更改为:

<jar-file>other-${my.final.version}.jar</jar-file>

然后,在other的pom.xml中,添加:

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>

启用过滤告诉 maven 替换变量。

如果您不想对所有资源进行过滤(出于性能或其他原因),您可能希望微调过滤。在 .

下查找标签 includes

【讨论】:

  • 对不起,如果你误会了:当ear 被构建时,它里面的ejbs 的依赖树就被解析了。我耳中的不同罐子可能取决于不同版本的other.jar。只有这些版本中的一个被放入耳中(在依赖调解之后)。但是在构建 jars 的过程中,我们无法知道哪个版本在 ear 的依赖中介中“获胜”。罐子通常比耳朵早得多。
  • 我的错!所以我的回答根本不相关。您可以查看 ${maven.dependency.GROUP_ID.ARTIFACT_ID.jar.path},它返回实际 jar 依赖项的完整路径。即使这样,您也需要找到一种方法来去除路径以便只保留文件名......
【解决方案3】:

所以,就像您自己说的,当您构建 EAR 时,您的工件已构建,jar-file 已定义且无法更改。因此,有两种选择:

  1. jar-file 必须是特定版本 - 不允许使用其他版本
  2. jar-file 可以是任何版本 - 从 jar 名称中排除版本

1.严格版

您可以使用single-version range 强制 Maven 仅考虑特定版本的依赖项:

<dependency>
  <groupId>my.company</groupId>
  <artifactId>persistence</artifactId>
  <!-- require specifically this version -->
  <version>[1.0.2]</version>
</dependency>

2。从 jar 名称中排除版本

您可以使用任何名称将 jars 添加到 EAR,even without version:

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-ear-plugin</artifactId>
        <version>2.10.1</version>
        <configuration>
           <modules>
             <ejbModule>
               <groupId>my.company</groupId>
               <artifactId>persistence</artifactId>
               <!-- rename artifact in ear -->
               <bundleFileName>persistence.jar</bundleFileName>
             </ejbModule>
          </modules>
        </configuration>
      </plugin>
    </plugins>
  </build>

【讨论】:

  • 您还可以从 EAR 中的所有工件中删除版本:maven.apache.org/plugins/maven-ear-plugin/examples/…
  • 您还可以将版本范围与 Maven 属性结合起来:&lt;version&gt;[${persistence.version}]&lt;/version&gt;
  • 谢谢,但恐怕这不太令人满意。第一个解决方案违背了我们公司构建耳朵的方式(一个中心组收集版本 - 我无法提前修复版本)。第二种解决方案肯定会起作用,但违反了 Maven 将版本号放在文件名中的方式。不过,如果我没有更好的方法,我将使用第二个版本(如您的评论)作为解决方法,直到出现更好的方法。
猜你喜欢
  • 2013-06-06
  • 2014-12-19
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
  • 2013-12-30
  • 2020-04-09
相关资源
最近更新 更多