Java EE7和Maven工程入门(4)

目录

  1. 一个简单Maven工程的结构
  2. 建立一个简单的WAR工程
  3. 定义ejb services模块和jpa实体模块
  4. 定义EAR模块
  5. 使用Arquillian进行单元测试(上)
  6. 使用Arquillian进行单元测试(下)
  7. 使用PostagreSQL与ShrinkWrap API进行测试

我们现在开始第四部分。目前我们的简单工程包含了:

1.一个web maven模块(war)
2.一个支持无状态会话beans的ejb模块(EJB3.1)
3.支持实体beans的ejb模块(JPA2)

但是,我们仍然缺少把它们打包到一起的存档文件,即‘ear’类型(亦称企业存档)

定义EAR maven模块

在下图可以看到,我们在sample-parent下定义了一个空文件夹,叫做sample-ear。这个文件夹需要有一个pom.xml文件。我们的新模块需要被sample-parent\pom.xml的“modules”部分正确引用。

EAR MAVEN模块的主要目的是为了“配置”著名的maven-ear插件,这个插件将会被maven引用,并且用来生成我们最后的部署应用程序。

有两件简单的事情需要做:为maven-ear插件增加配置和在EAR模块增加我们的“内部”应用依赖关系,以便让它“知道”应该寻找哪个模块。我们来看一看:

ear pom.xml内容

<build>
   <finalName>sampleapp</finalName>
    <plugins>
       <!--Ear plugin -creating the ear - watch out skinny WARS!-->
        <plugin>
           <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-ear-plugin</artifactId>
            <configuration>
              <finalName>sampleapp</finalName>
                <defaultJavaBundleDir>lib/</defaultJavaBundleDir>
                <skinnyWars>true</skinnyWars>
                 <modules>
                      <webModule>
                         <groupId>gr.javapapo</groupId>
                         <artifactId>sample-web</artifactId>
                       </webModule>
                        <ejbModule>
                           <groupId>gr.javapapo</groupId>
                           <artifactId>sample-services</artifactId>
                       </ejbModule>
                 </modules>
            </configuration>
         </plugin>
     </plugins>
</build>

上面是创建过程,下面是需要注意的地方:

  • 记得我们在另一个模块中的做法。我们已经为插件定义了一些常用的基本配置,在“父”pom中。可以回顾一下那里已经做好的配置。
  • 注意“defaultJavaBundleDir”。这是我们所有库定义的地方(除了包含ear的顶层模块,通常也包会含ear的’lib’子文件夹)。
  • 什么是顶层模块?它实际上是,将会打包在ear中的jar包和wars包,而且将会被看成是一等公民。正如你知道的,我们定义了两个顶层模块,sample-web和sample-services。
  • 注意’skinnyWars‘属性。当该属性启用时,我们会对war项目中引用的第三方库打包时执行一个确定的模型。简单来说,我们的war档案会包含任何WEB-INF\lib文件夹中定义依赖的外部函数库。和这些libs相反,它们将在ear级’defaultJavaBundleDir‘路径上打包。

如果不添加ear-pom的“依赖关系”,上述的配置无法工作。

<!-- our in app dependencies-->
    <dependencies>
        <dependency>
            <groupId>gr.javapapo</groupId>
            <artifactId>sample-web</artifactId>
            <version>${project.version}</version>
            <type>war</type>
        </dependency>

        <dependency>
            <groupId>gr.javapapo</groupId>
            <artifactId>sample-services</artifactId>
            <version>${project.version}</version>
            <type>ejb</type>
        </dependency>
    </dependencies>

请注意下面内容:

  • 在这个pom上的依赖元素,需要“type”属性。

一个很好的问题:sample-domain(jar)模块在哪里?

好吧,这个模块在ear中不会提升为顶级模块。因为我们将会把作为sample-services模块的一个依赖关系,所以我们的services将在实体beans模块拥有一个依赖关系(听起来很公平)。因此需要更新sample-services模块的pom.xml。

 <artifactId>sample-services</artifactId>
  <name>sample-services</name>   
   <description>EJB service layer</description>
        <packaging>ejb</packaging>
        <dependencies>
            <dependency>
                <groupId>javax</groupId>
                <artifactId>javaee-api</artifactId>
           </dependency>
           <dependency>
             <groupId>gr.javapapo</groupId>
             <artifactId>sample-domain</artifactId>
             <version>${project.version}</version>
          </dependency>
        </dependencies>
</project>

这样,sample-services.jar会和sample-domain.jar一起被“获取(fetch)”。默认情况下(记住Maven都是约定),当我们给一个ear定义一个顶级模块,像sample-services,它的依赖关系在ear的defaultJavaBundleDir库中是自动绑定的!所以,当我们打包ear时,将会看到打包的sample-domain.jar。

再次失踪的依赖关系

在第一个services模块和实体模块的应用依赖关系之后,我们还需要另外一个依赖关系。我们的war模块(web层面)将会用到一些services。为了做到这一点,需要在“services”模块有一个依赖关系。所以相应的,在sample-web项目上需要pom.xml。

 <packaging>war</packaging>
        <build>
         <finalName>${project.artifactId}</finalName>
        </build>
          <dependencies>
             <dependency>
                   <groupId>javax</groupId>
                    <artifactId>javaee-api</artifactId>
                     <scope>provided</scope>
             </dependency>
            <dependency>
              <groupId>gr.javapapo</groupId>
              <artifactId>sample-services</artifactId>
            <version>0.0.1-SNAPSHOT</version>
           </dependency>
        </dependencies>

让我们来打包war吧

现在我们准备好了。基本的依赖关系都设置好了,ear已经配置,我们只需要打包了。在sample-parent文件夹下,只需在命令行输入:

mvn clean package

我们就完成了。让我们检查一下sample-ear模块的’target’文件夹,最终的ear已经生成了。maven还在ear中创建了’exploded’版本,(下图是放大版本)。请注意,我们的两个顶级ear元素,以及sample-domain.jar是如何在ear的’lib’文件夹下的。同时还需要注意一些基本的库,像javaee-api.jar,并没有包含在lib文件夹下。既然我们已经添加了规定的“pom”(见xml的最终版本)。

最后的工作:skinny war和MANIFEST.MF文件

最后,我们可以在这里结束。最后的ear是对的并且可以工作了,但是和所有上述的配置一起,特别是根据我们的喜好的设置来创建skinny wars。需要注意的一个细节:MANIFEST文件是jar和war中的特殊描述符。应用服务器通过MANIFEST文件定位和加载classpath上“依赖”的jar包。

有一个小问题存在于sample-web.war的MANIFEST.MF文件中。解压已生成的war文件,用文本编辑器打开MANIFEST.MF,会看到类似下面的内容:

Manifest-Version: 1.0
Built-By: papo
Build-Jdk: 1.7.0_45
Class-Path: lib/sample-services-0.0.1-SNAPSHOT.jar lib/sample-services-0.0
 .1-SNAPSHOT.jar lib/sample-domain-0.0.1-SNAPSHOT.jar
Created-By: Apache Maven 3.2.1
Archiver-Version: Plexus Archiver

你能找到错误吗?默认生成的MANIFEST.MF中,顶级ejb jars(sample-services)指向了一个错误路径。我们的sample-services.jar并没有放在ear中的\lib下,而是一个顶级元素。所以,怎样创建一个正确的MANIFEST呢?

最后,我们需要微调一下maven-war插件。我们需要在父pom中覆盖指定的默认行为,并为这个特殊的依赖关系指定一个正确项。如果碰巧有多个,那么需要为所有的在配置中的顶级元素的jars添加(请确保你正确的做了这一点,在条目之间使用一个空格)。所以,在sample-war pom中,我们需要在一个应用的顶层增加一些(额外的)配置。

在stackoverflow上有一个有趣的问题。如果使用skinny-wars的话,你可以从这里了解更多的小窍门或者其他可能的解决方法。

就是这样,ear模块已经准备就绪。

总结

点击这个Git Tag可以看到这篇文章的最终版。到这篇文章为止,我们已经完成了第一个系列的文章。从零开始,应用基本的maven准则为Java企业级应用构建一些基本的maven模块。你可以使用这个例子,任意扩展满足你的需求。迄今为止它完全满足你的所有需求,它是Maven开始、思考和配置的一个很好的实例。

接下来的文章将会扩充这个例子,加入更多maven的模块,使用更多maven的功能。

原文链接: javacodegeeks 翻译: ImportNew.com - mathshelly
译文链接: http://www.importnew.com/13530.html
[ 转载请保留原文出处、译者和译文链接。]

关于作者: mathshelly

(新浪微博:@mathshelly

查看mathshelly的更多文章 >>



相关文章

发表评论

Comment form

(*) 表示必填项

还没有评论。

跳到底部
返回顶部