Maven2: Best practice for Enterprise Project (EAR file)

162,168

Solution 1

You create a new project. The new project is your EAR assembly project which contains your two dependencies for your EJB project and your WAR project.

So you actually have three maven projects here. One EJB. One WAR. One EAR that pulls the two parts together and creates the ear.

Deployment descriptors can be generated by maven, or placed inside the resources directory in the EAR project structure.

The maven-ear-plugin is what you use to configure it, and the documentation is good, but not quite clear if you're still figuring out how maven works in general.

So as an example you might do something like this:

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

Solution 2

What helped me a lot was to run the Maven archetype:generate goal and select from one of the archetypes, some of which seem to be updated regularly (in particular JBoss seems to be well maintained).

mvn archetype:generate

Hundreds of archetypes appeared in a numbered list from which to select (519 as of now!). The goal, still running, prompted me to make a selection by entering a number or entering a search string e.g.:

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

I entered the search string "ear," which reduced the list to only 8 items (as of today):

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

I selected "org.jboss.spec.archetypes:jboss-javaee6-ear-webapp" (by entering the selection "5" in this example).

Next, the goal asked me to enter the groupId, artifactId, package names, etc., and it then generated the following well-documented example application:

[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

After reading the four POM files, which were well-commented, I had pretty much all the information I needed.

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

Solution 3

i have made a github repository to show what i think is a good (or best practices) startup project structure...

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

some keywords:

  • Maven 3
  • BOM (DependencyManagement of own dependencies)
  • Parent for all Projects (DependencyManagement from external dependencies and PluginManagement for global Project configuration)
  • JUnit / Mockito / DBUnit
  • Clean War project without WEB-INF/lib because dependencies are in EAR/lib folder.
  • Clean Ear project.
  • Minimal deployment descriptors for Java EE7
  • No Local EJB Interface because @LocalBean is sufficient.
  • Minimal maven configuration through maven user properties
  • Actual Deployment Descriptors for Servlet 3.1 / EJB 3.2 / JPA 2.1
  • usage of macker-maven-plugin to check architecture rules
  • Integration Tests enabled, but skipped. (skipITs=false) useful to enable on CI Build Server

Maven Output:

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

Solution 4

NetBeans IDE automatically defines the structure which is almost similar to one suggested by Patrick Garner. For NetBeans users

File->New Project ->In left side select Maven and In right side select Maven Enterprise Application and press Next -> Asks for project names for both war,ejb and settings.

The IDE will automatically create the structure for you.

Solution 5

This is a good example of the maven-ear-plugin part.

You can also check the maven archetypes that are available as an example. If you just runt mvn archetype:generate you'll get a list of available archetypes. One of them is

maven-archetype-j2ee-simple
Share:
162,168

Related videos on Youtube

Maik
Author by

Maik

Updated on February 26, 2020

Comments

  • Maik
    Maik over 4 years

    I am just switching from Ant to Maven and am trying to figure out the best practice to set up a EAR file based Enterprise project?

    Let's say I want to create a pretty standard project with a jar file for the EJBs, a WAR file for the Web tier and the encapsulating EAR file, with the corresponding deployment descriptors.

    How would I go about it? Create the project with archetypeArtifactId=maven-archetype-webapp as with a war file, and extend from there? What is the best project structure (and POM file example) for this? Where do you stick the ear file related deployment descriptors, etc?

    Thanks for any help.

  • Mike Cornell
    Mike Cornell almost 14 years
    I found my own answer a year later when I had the same question. Good job self!
  • Ian McLaird
    Ian McLaird about 12 years
    This works, but it does end up putting a bunch of jboss-specific dependencies into your project, which you may or may not want to clean up after the fact.
  • Vihung
    Vihung about 12 years
    maven-archetype-j2ee-simple seems unnecessarily complex in structure - particularly with modules inside modules, and separate modules for things like logging. I did not understand the rationale behind this structure
  • Sym-Sym
    Sym-Sym over 10 years
    I agree with you, specially when adhering to JEE6 specifications
  • gammay
    gammay over 10 years
    For me this worked when I set type as ejb <type>ejb</type>
  • Jörg
    Jörg over 9 years
    I really like your packaging and architectural approach. You should think about packaging your project as a maven archetype.
  • sschober
    sschober over 8 years
    Very nice solution! I have one question though: why not pack the BOM stuff into the parent project? why the additional layer?
  • StefanHeimberg
    StefanHeimberg over 8 years
    cause of separation of concerns. the bom could be imported by other projects. they need only the dependencyManagement of your dependencies and not the dependencyManagement of the dependencies you are using. ok. you can say that if nobody is using your project this additional layer is not nessecary.. but i think that it make sense too... readability. the dependencyManagement of the parent project is not mixed with your dependencies... in a bigger project with > 50 internal maven projects the dependencyManagement inside the parent project could be a mess..
  • StefanHeimberg
    StefanHeimberg over 8 years
    another reason is that this is the same structure as documented at maven.apache.org/guides/introduction/…. this helps to work in a team where the team members often change becaus it is the "default" documented way.
  • StefanHeimberg
    StefanHeimberg over 8 years
    BTW. i have created a GitHub project once to show how a multi project setup could be done: github.com/StefanHeimberg/maven3-multiapplication-setup (for a company internal discussion)
  • Farrukh Najmi
    Farrukh Najmi over 7 years
    Great answer! I would like to suggest that Gradle be used instead of Maven 3 in first bullet. It has all the benefits of maven and in addition has all the power of Groovy, a Java like programming language, that can be used to write very powerful build scripts.
  • DiegoAlfonso
    DiegoAlfonso over 5 years
    That pom throws some warnings: 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-ear-plugin is missing and 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing, so you might want to update your otherwise great answer
  • Paco Abato
    Paco Abato almost 4 years
    The link throws an unauthorized error. And that's the reason for writing complete solutions instead of relying on links.