Maven2:企业项目(EAR文件)的最佳实践

103

我刚从Ant转到Maven,正在尝试找出设置基于EAR文件的企业项目的最佳实践。

假设我想创建一个标准的项目,其中包含一个用于EJBs的jar文件,一个用于Web层的WAR文件以及封装了它们的EAR文件,同时也包含相应的部署描述符。

我该如何操作呢?像创建WAR文件一样使用archetypeArtifactId=maven-archetype-webapp创建项目,并从那里扩展吗?对于这种情况下的最佳项目结构(以及POM文件示例),应该如何设计?在哪里放置与EAR文件相关的部署描述符等呢?

非常感谢任何帮助。

6个回答

99
你创建了一个新项目。新项目是你的EAR组装项目,它包含你的EJB项目和WAR项目的两个依赖项。
所以实际上你有三个Maven项目。一个EJB项目。一个WAR项目。一个EAR项目将这两个部分合并在一起并创建EAR文件。
部署描述符可以由Maven生成,也可以放置在EAR项目结构中的资源目录中。
你需要使用maven-ear-plugin来配置它,文档很好,但如果你还在搞清楚Maven的工作原理,则不太清晰。
因此,例如,你可能会像这样做:
<?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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany</groupId>
  <artifactId>myEar</artifactId>
  <packaging>ear</packaging>
  <name>My EAR</name>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-ear-plugin</artifactId>
        <configuration>
          <version>1.4</version>
          <modules>
            <webModule>
              <groupId>com.mycompany</groupId>
              <artifactId>myWar</artifactId>
              <bundleFileName>myWarNameInTheEar.war</bundleFileName>
              <contextRoot>/myWarConext</contextRoot>
            </webModule>
            <ejbModule>
              <groupId>com.mycompany</groupId>
              <artifactId>myEjb</artifactId>
              <bundleFileName>myEjbNameInTheEar.jar</bundleFileName>
            </ejbModule>
          </modules>
          <displayName>My Ear Name displayed in the App Server</displayName>
          <!-- If I want maven to generate the application.xml, set this to true -->
          <generateApplicationXml>true</generateApplicationXml>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>
    </plugins>
    <finalName>myEarName</finalName>
  </build>

  <!-- Define the versions of your ear components here -->
  <dependencies>
    <dependency>
      <groupId>com.mycompany</groupId>
      <artifactId>myWar</artifactId>
      <version>1.0-SNAPSHOT</version>
      <type>war</type>
    </dependency>
    <dependency>
      <groupId>com.mycompany</groupId>
      <artifactId>myEjb</artifactId>
      <version>1.0-SNAPSHOT</version>
      <type>ejb</type>
    </dependency>
  </dependencies>
</project>

105
一年后我又有同样的问题,但这次我找到了自己的答案。好样的,自己! - Mike Cornell
1
当我将 type 设置为 ejb 时,这对我起作用了 <type>ejb</type> - gammay
那个pom文件会抛出一些警告:org.apache.maven.plugins:maven-ear-plugin'build.plugins.plugin.version'缺失,以及org.apache.maven.plugins:maven-compiler-plugin'build.plugins.plugin.version'缺失。因此,您可能需要更新您原本很好的答案。 - DiegoAlfonso

47

对我有很大帮助的是运行Maven的archetype:generate目标,并从其中一个原型中进行选择,其中一些似乎定期更新(特别是JBoss似乎得到了良好的维护)。

mvn archetype:generate

从中选择的编号列表中出现了数百个原型(目前为止有519个!)。 这个仍在运行的目标促使我通过输入数字或输入搜索字符串来进行选择,例如:

513: remote -> org.xwiki.commons:xwiki-commons-component-archetype
514: remote -> org.xwiki.rendering:xwiki-rendering-archetype-macro
515: remote -> org.zkoss:zk-archetype-component
516: remote -> org.zkoss:zk-archetype-webapp
517: remote -> ru.circumflex:circumflex-archetype (-)
518: remote -> se.vgregion.javg.maven.archetypes:javg-minimal-archetype (-)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains):

我输入了搜索字符串"ear",结果列表只有8个项目(截至今天):

Choose archetype:
1: remote -> org.codehaus.mojo.archetypes:ear-j2ee14 (-)
2: remote -> org.codehaus.mojo.archetypes:ear-javaee6 (-)
3: remote -> org.codehaus.mojo.archetypes:ear-jee5 (-)
4: remote -> org.hibernate:hibernate-search-quickstart (-)
5: remote -> org.jboss.spec.archetypes:jboss-javaee6-ear-webapp 
6: remote -> org.jboss.spec.archetypes:jboss-javaee6-webapp-ear-archetype
7: remote -> org.jboss.spec.archetypes:jboss-javaee6-webapp-ear-archetype-blank
8: remote -> org.ow2.weblab.tools.maven:weblab-archetype-searcher

我选择了"org.jboss.spec.archetypes:jboss-javaee6-ear-webapp"(在这个例子中输入选择"5")。接下来,向导要求我输入groupId、artifactId、package名称等信息,然后生成以下文档良好的示例应用程序:

[pgarner@localhost Foo]$ tree
.
|-- Foo-ear
|   `-- pom.xml
|-- Foo-ejb
|   |-- pom.xml
|   `-- src
|       |-- main
|       |   |-- java
|       |   |   `-- com
|       |   |       `-- foo
|       |   |           |-- controller
|       |   |           |   `-- MemberRegistration.java
|       |   |           |-- data
|       |   |           |   `-- MemberListProducer.java
|       |   |           |-- model
|       |   |           |   `-- Member.java
|       |   |           `-- util
|       |   |               `-- Resources.java
|       |   `-- resources
|       |       |-- import.sql
|       |       `-- META-INF
|       |           |-- beans.xml
|       |           `-- persistence.xml
|       `-- test
|           |-- java
|           |   `-- com
|           |       `-- foo
|           |           `-- test
|           |               `-- MemberRegistrationTest.java
|           `-- resources
|-- Foo-web
|   |-- pom.xml
|   `-- src
|       `-- main
|           |-- java
|           |   `-- com
|           |       `-- foo
|           |           `-- rest
|           |               |-- JaxRsActivator.java
|           |               `-- MemberResourceRESTService.java
|           `-- webapp
|               |-- index.html
|               |-- index.xhtml
|               |-- resources
|               |   |-- css
|               |   |   `-- screen.css
|               |   `-- gfx
|               |       |-- banner.png
|               |       `-- logo.png
|               `-- WEB-INF
|                   |-- beans.xml
|                   |-- faces-config.xml
|                   `-- templates
|                       `-- default.xhtml
|-- pom.xml
`-- README.md

32 directories, 23 files

阅读了四个注释详细的POM文件后,我已经获得了几乎所有需要的信息。

./pom.xml
./Foo-ear/pom.xml
./Foo-ejb/pom.xml
./Foo-web/pom.xml

3
这个方法可行,但是它会在您的项目中添加很多JBoss特定的依赖项,您可能需要在事后对其进行清理,具体是否需要取决于您的需求。 - Ian McLaird
现在,11年过去了,有26个选项。安装其中一个选项后,需要对pom.xml文件进行一些工作(特别是将插件和依赖版本更新到最新水平),但尽管如此,这仍然是一种非常简单的安装有效的ear开发结构的方法。 - undefined

24

我创建了一个GitHub仓库来展示我认为是一个好的(或最佳实践的)初始项目结构...

https://github.com/StefanHeimberg/stackoverflow-1134894

一些关键词:

  • Maven 3
  • BOM (自有依赖的DependencyManagement)
  • 所有项目的父级(来自外部依赖项的DependencyManagement和全局项目配置的PluginManagement)
  • Junit / Mockito / DBUnit
  • 干净的War项目,没有WEB-INF/lib,因为依赖项在EAR/lib文件夹中。
  • 干净的Ear项目。
  • Java EE7的最小部署描述符
  • 没有Local EJB接口,因为@LocalBean就足够了。
  • 通过maven用户属性的最小Maven配置
  • Servlet 3.1 / EJB 3.2 / JPA 2.1的实际部署描述符
  • 使用macker-maven-plugin检查架构规则
  • 启用集成测试,但被跳过(skipITs=false),在CI构建服务器上启用很有用

Maven输出:

Reactor Summary:

MyProject - BOM .................................... SUCCESS [  0.494 s]
MyProject - Parent ................................. SUCCESS [  0.330 s]
MyProject - Common ................................. SUCCESS [  3.498 s]
MyProject - Persistence ............................ SUCCESS [  1.045 s]
MyProject - Business ............................... SUCCESS [  1.233 s]
MyProject - Web .................................... SUCCESS [  1.330 s]
MyProject - Application ............................ SUCCESS [  0.679 s]
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 8.817 s
Finished at: 2015-01-27T00:51:59+01:00
Final Memory: 24M/207M
------------------------------------------------------------------------

2
我非常喜欢你的打包和架构方法。你应该考虑将你的项目打包成一个Maven原型。 - Jörg
2
非常好的解决方案!不过我有一个问题:为什么不把BOM内容打包到父项目中?为什么要增加额外层级? - sschober
1
解耦合的原因是为了方便其他项目导入BOM。它们只需要使用你的依赖关系的dependencyManagement,而不需要使用你所使用的依赖关系的dependencyManagement。如果没有人在使用你的项目,你可以说这个额外的层次不是必需的...但我认为它也有意义...可读性。父项目的dependencyManagement与你的依赖关系不混合......在一个大型的>50个内部Maven项目的项目中,父项目中的dependencyManagement可能会变得混乱不堪... - StefanHeimberg
2
另一个原因是这与http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html中记录的结构相同。这有助于在团队中工作,因为团队成员经常更改,因为这是“默认”的记录方式。 - StefanHeimberg
2
顺便说一句,我曾经创建了一个 GitHub 项目,以展示如何进行多项目设置:https://github.com/StefanHeimberg/maven3-multiapplication-setup(供公司内部讨论使用) - StefanHeimberg
很棒的答案!我想建议在第一条中使用Gradle而不是Maven 3。它具有所有Maven的优点,另外还具有Groovy的全部功能,这是一种类似于Java的编程语言,可以用来编写非常强大的构建脚本。 - Farrukh Najmi

7
NetBeans IDE会自动定义结构,该结构与Patrick Garner建议的结构几乎相同。对于NetBeans用户来说:
文件->新建项目->在左侧选择Maven,在右侧选择Maven企业应用程序,然后点击“下一步”->要求为war、ejb和设置命名项目。
IDE将自动为您创建结构。

我同意你的观点,特别是遵循JEE6规范。 - Sym-Sym

3

10
“maven-archetype-j2ee-simple” 结构复杂,尤其是模块中有子模块,并且为诸如日志记录之类的内容单独设置了模块。我不理解这种结构背后的原因。 - Vihung

2

我一直在寻找一个完整的基于Maven打包的EAR应用程序的端到端示例,最终偶然发现了这个。说明中建议在CLI中运行时选择选项2,但为了您的目的,请使用选项1。


该链接抛出未经授权的错误。这就是编写完整解决方案而不依赖链接的原因。 - Paco Abato

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接