Maven 2’s EAR plugin gives me a headache

While maven 2 is all cool and such. It can indead use some more documentation.

Try building this with Maven 2:

  • EJB’s should be passed through IBM WebSphere’s 5.1 EJB Deploy.
  • Most application dependencies should be packaged into the resulting EAR file, and NOT into the war file.
  • Jar files packaged at the EAR level should be mentioned in the relevant manifest class-path entries of several WAR files.
  • There is a preference to give a packaged EJB jar in the EAR a specific name.
  • It should all be done in one single build. Execute one pom to the requested build phase and it should be done.

Well let’s get started… I won’t be pasting entire POMs, but do expect some links and snippets.

EJB’s should be passed through IBM WebSphere’s 5.1 EJB Deploy.

I can’t find any Maven 2 plugin capable of running EJB Deploy on EJB’s. Oh well, I’ll just role my own and use a MOJO to execute through the System class of Java. No problem with that. Next I should make sure that the specific file is published to the repsoitory. No problem with that, just enter this line at the end of your MOJO’s execute method:
projectHelper.attachArtifact( project, "ejb-ibm", "ibm", ibmJarFile );
(Note that the ibmJarFile is a Java File initialized with the IBM EJBDeploy output jar placed in the target directory of the ejb project. So EJBDeploy gets executed and outputs the Jar with IBM stub code in the target directory of the EJB project. The name of the Jar file isn’t really important, but you should follow Maven’s file naming conventions and use something like MyEjb-ibm.jar.)

Ok, so now EJB Deploy creates a nice EJB Jar file with all kinds of IBM stub code in it. Sweet! And that little line I showed, have a peak at the Maven EJB Mojo for inspiration, it also shows how you can get a projectHelper. Cool, lets execute this.

Building seems to be ok, but when I want other files to depend on my IBM version of the EJB something is wrong. It can not be found. I did specify a type in my dependency declarion in the depending POM.


See, how I declared ejb-ibm? Sort of the same way you can depend on a ejb-client jar. The error I get from Maven is rather misleading, something about not being able to find the artifact in the remote repository. Let’s open up the local repository after running an install on the EJB project. Strangely there is a file there named: MyEjb-0.0.1.ejb-ibm So Maven is rather creative with the naming. Must be some default behaviour. Well to cut this short I needed to define a custom Artifact type within my plugin. I found this little gem at only one single bit of documentation: Introduction to the Build Lifecycle Look for a paragrapg titled: Creating a Custom Artifact Handler

It involves defining a plexus addition with some kind of components.xml file. See the linked doc for more info. I put this custom artifact declaration into my EJB Deploy MOJO. Don’t forget to declare extensions: true when binding the your plugin to the life cycle.

Let’s try again. Everything works now, EXCEPT the maven-ear-plugin. Atleast, ehm the dependences get resolved and they are included with the ibm classifier in the manifest’s class-paths and EAR/WARs. (file names looking like MyEjb-0.0.1-ibm.jar) Close, but not good enough, I want control over my EJB jar file naming. AND I have to get the maven-ear-plugin to eat my configuration. Because right now it’s just crashing with a nasty error declaring that the ejb-ibm type is not a recognized type.

So I’m still not there yet. Now I only need to convince the EAR plugin, since to my knowledge it is the last problem I need to tackle. So let’s look up the maven-ear-plugin documentation, which states something about customizing modules. The good news, there is some statement about a classifier which I can configure. So I hope that this will allow me to select my ejb-ibm artifact type, since all the other documentation states that the ibm part of my custom artifact is called a classifier (MyEjb-0.0.1-ibm.jar). I do know module configurations give me exact control over the resulting ejb jar file names. More on this on monday. Tried it and it works.

Most application dependencies should be packaged into the resulting EAR file, and NOT into the war file.
You should declare the relevant dependencies as dependencies of your relevant EAR projects. Then all you need to do is make sure the jar file is mentioned in the WAR using the JAR and make sure the JAR isn’t packaged in the WAR file.

Jar files packaged at the EAR level should be mentioned in the relevant manifest class-path entries of several WAR files.
This combines with the above explanation. You let the EAR project depend on the artifact. Next you let the WAR file depend on the same artifact. And you declare that the maven-war-plugin should addClasspath as described here.
First guess would be to give the dependency a provided scope right? WRONG! Provided should be used for platform dependencies like J2EE jar. This one is a stupid trick. Instead of using a provided scope, drop the scope declaration and declare the dependency as optional. Now in my book an optional dependency is kind of misleading, but hey it works. I get my manifest class-path declaration and it’s not included in the war itself.

There is a preference to give a packaged EJB jar in the EAR a specific name.
See my longer explanation above. Something with using Module configurations within the maven-ear-plugin.

As you can tell, this post is sort of a brain dump to get this info out there. I am not aware of any proper documentation on the problems I encountered. So it might be a bit terse to read. If you have any questions or would like to know some more details. Post a comment, I’ll do my best to elaborate.

5 Replies to “Maven 2’s EAR plugin gives me a headache”

  1. I’m trying to convert an old J2EE project to use M2’s EAR plugin, and I have some questions for you please:
    1. Does the EAR plugin expect a certain project directory structure? If so, is it documented somewhere?
    2. The “archetype” plugin can generate the structure for a “simple” J2EE project. Did you use that to create your project’s structure, or did you create yours manually?
    3. Could you please post your project’s structure and your POM?

    Thanks for any help,

    Andrew (andrews [att] bisinfo [dott] com [dott] au)

  2. Hello Andrew,

    Check your mailbox. While I can’t send around actual project related material because of NDAs and stuff, I can send you some sterilized information.

    Hope the info helps.

    For the rest of the world, here is the meat from my reply to Andrew:

    Your questions:
    1: Yes. Use mvn help:effective-pom It shows you all defaults. But the good thing is, you can modify all that. We’ve modified our EJB, WAR and EAR projects to match RAD6 directory structure. Maven adapts easily to that, while RAD6 is not able to do it the other way around.

    2. No. I’ve taken the RAD6 structure as is. Everything on a single level in a directory tree. Modules and parents can be indicated with relative paths. We pick the right EJBs, WARs and JARs up by declaring them as a dependency. Check the various scope options for dependencies and understand them.

    3. I can’t post it, bu can describe it. Take the structure as generated by RAD6. Adapt Maven to that. Create a “project” pom in a project dir on the same level as all RAD6 projects.

    My project root
    |-EJB1 project
    |-EJB2 project
    |-WAR project
    |-JAR project
    |-EAR project
    |-Project project

    The project project has all other projects as modules (by using relative paths). The EAR project has the various required EJBs, WARs and JARs as dependencies. Also the project project is declared as parent by all other projects.

    Also note the documention on the EAR, EJB and WAR plugin pages.

    Don’t forget the examples. Also a good reference is Beter Builds with Maven. It’s a free download only a registration is required. It actually is a must read:

Comments are closed.