12

我有一个 Java EE 项目。该项目是使用 maven 构建到 .ear 存档中的。有一个包含 JPA 2 持久性单元的库 jar,它位于 ear 的库目录中(因此多个其他模块可以使用它)。

在此持久性单元中添加 Shiro 的 Permission 接口的实现作为实体时,我无法正确部署耳朵,因为 shiro 类在持久性单元中不可用。我最终发现我需要将库 jar 的所有依赖项(也适用于传递 deps)放在库目录中以使其部署。

所以最终的布局大概是这样的:

ear
`- lib
   `- persistence-unit.jar
    - shiro-core.jar
    - slf4j-api.jar
 - module1
 - moduleN
 - library1.jar
 - libraryN.jar

现在,对于问题:

  1. 是否有关于应该在库目录中放置什么的指导方针,我的解决方案是否普遍可以接受?
  2. 为什么耳朵根目录下的库对 lib 目录中的 jar 不可用?
  3. 为什么 Maven 不自动解决这个问题?

编辑:耳朵的 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <artifactId>ear</artifactId>
    <packaging>ear</packaging>

    <parent>
        <groupId>com.example</groupId>
        <artifactId>project</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ear-plugin</artifactId>
                <version>2.7</version>
                <configuration>
                    <modules>
                        <webModule>
                            <!-- ... -->
                        </webModule>
                        <ejbModule>
                            <!-- ... -->
                        </ejbModule>
                        <jarModule>
                            <groupId>com.example</groupId>
                            <artifactId>persistence-unit</artifactId>
                            <bundleDir>lib</bundleDir>
                        </jarModule>

                        <-- I added these to get the deployment working -->
                        <jarModule>
                            <groupId>org.apache.shiro</groupId>
                            <artifactId>shiro-core</artifactId>
                            <bundleDir>lib</bundleDir>
                        </jarModule>
                        <jarModule>
                            <groupId>org.slf4j</groupId>
                            <artifactId>slf4j-api</artifactId>
                            <bundleDir>lib</bundleDir>
                        </jarModule>
                    </modules>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>persistence-unit</artifactId>
        </dependency>
        <dependency>
            <!-- ... -->
            <type>war</type>
        </dependency>
        <dependency>
            <!-- ... -->
            <type>ejb</type>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
        </dependency>
    </dependencies>
</project>

对于持久性单元:

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <artifactId>persistence-unit</artifactId>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.example</groupId>
        <artifactId>project</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.jboss.spec</groupId>
            <artifactId>jboss-javaee-6.0</artifactId>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
        </dependency>
    </dependencies>
</project>
4

3 回答 3

8

是否有关于应该在库目录中放置什么的指导方针,我的解决方案是否普遍可以接受?

您几乎已经搞定了,应该对所有 EAR 模块都可用的 JAR 应该放在这里。

为什么耳朵根目录下的库对 lib 目录中的 jar 不可用?

它通常以相反的方式工作,lib文件夹中的 JAR 可供根目录中的 JAR 使用。但是,我相信您可以通过以下方式实现此目的<includeInApplicationXml>

<jarModule>
    <groupId>org.nisse</groupId>
    <artifactId>hue</artifactId>
    <includeInApplicationXml>true</includeInApplicationXml>
</jarModule>

为什么 Maven 不自动解决这个问题?

我假设您的意思是 maven 不会自动将所有传递依赖项放入lib? 我相信它应该这样做,而且确实——你能不能显示你的 POM 的相关部分?

编辑:您的 EAR 模块应该只引用 EJB JAR 和 WAR 作为依赖项。任何传递依赖项都应该自动包含在 EAR 中,默认情况下在顶层 - 这可以用<defaultLibBundleDir>ear-plugin 中的标签覆盖<configuration>

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.7</version>
<configuration>
    <defaultLibBundleDir>lib</defaultLibBundleDir>
    <archive>
        <manifest>
            <addClasspath>true</addClasspath>
        </manifest>
    </archive>
    <modules>
       ... etc.

<archive>/部分还应<addClasspath>确保正确设置 MANIFEST 类路径。也许这正是您所缺少的?

干杯,

于 2013-02-14T10:41:39.050 回答
6

我不会评论 Maven 的配置,而只是评论库应该去哪里。

在 EAR 的模块之间共享库有两种主要机制 -捆绑库(在Java EE 6 规范中的 EE.8.2.1 中描述)和已安装库(EE.8.2.2)。

已安装的库与 EAR 分开安装,因此在应用程序服务器上的许多 EAR 之间共享。

捆绑库可以安装在lib(默认库目录)、由library-directoryEAR 的部署描述符的元素指定的目录和/或任何要被模块的Class-Path清单标头引用的目录中(或由模块引用的 jar turn 定义了一个传递库)。

我对 Java EE 6 规范的理解是Class-Path可以在 EAR 中的任何位置引用任何库,但是 jar 的内容会变成非 Java EE 模块。这意味着persistence.xml在部署时不考虑这一点,并且文件中定义的潜在持久性上下文不会在运行时生效。

在您的情况下,persistence-unit.jar似乎包含持久性单元配置并使它们可用于其他模块,它应该放在lib目录中。其他两个 jar -shiro-core.jar并且slf4j-api.jar- 可以在 EAR 中的任何位置(包括lib用于简单部署的目录 - 不需要Class-Path在任何引用库/模块中包含元素)。

将其包装起来,以简化部署,lib除非Class-Path使用并指向另一个目录,否则将您的库放在目录中。在这种情况下,您宁愿检查引用的 jar 文件是否不是具有持久性单元定义的 Java EE jar,因为它不会被正确部署(并且 PU 对模块不可用)。

于 2013-02-14T23:38:57.593 回答
4

这篇文章有一个很好的表格来解释事情:

表 2 标准档案可以加载打包在其中的类,也可以从它所依赖的任何其他档案中加载类。

Module      Code Sources
EAR 
            All JARs in the /lib directory of the EAR
            Manifest Class-Path of any JARs in 1
EJB-JAR 
            EJB-JAR file itself
            JARs referenced by manifest Class-Path of EJB-JAR
            JARs referenced by manifest Class-Path of above JARs (in 2)
WAR 
            WEB-INF/classes
            JARs in WEB-INF/lib
            JARs referenced by manifest Class-Path of WAR
            JARs referenced by manifest Class-Path of JARs in 2 and 3
于 2013-11-01T22:56:47.583 回答