views:

415

answers:

5

If this is answered somewhere else, kindly smack me and point me in the right direction.

I'm brand new to Maven and trying to wrap my head around how to use it with my projects. I've got two top level projects, one a Swing app, the other is a set of Web Services. They both depend on the same in-house jar. What are good ways to set up the poms for this?

If the jar was only used by one of the projects, then it looks like I'd move it down inside and make it a module. But I don't want two (and later more) copies of that jar's source code.

One way it looks like I could do this is to have a master pom for the Swing app that has the Swing app and the library jar as a modules. Then have another master pom for the Web app set up the same way. Would that make sense? Are there better ways?

The directory structure is currently very straightforward:

Development/  
----SwingApp/  
----WebServices/  
----CoreLibrary/


Way too much info and side questions follow:

I've inherited a "build system" (using the term loosely) which is 100% Netbeans autogenerated ant scripts. I started trying to put it into Continuous Integration, TeamCity, which I really like. I've run into serious problems trying to build the WebServices project with it. There are things in the generated ant (build-impl.xml) that cannot be overridden in the CI environment as far as I can tell. Combine this with some serious classpath hell in day to day development and you're starting to see why I want to go to maven.

One of the issues wrapped up in this question is a habit developers on my team all seem to have. Right now the various projects in Netbeans have project references to the "CoreLibrary" project. What this means is that when source is changed in "CoreLibrary" and the developer does a build on a top level app, it will also build the CoreLibrary as necessary. Can that be simulated in Maven? It would go a ways to ease the transition. So far I'm seeing that Netbeans (6.7) doesn't do that with maven builds, and I don't think I can sell (yet) doing the day-to-day build work outside of Netbeans.

A: 

Let each of the application and the jar library be a module inside a trivial parent. Let both applications depend on the core, and maven will figure out the order in which to build things.

ankon
A: 

I've got two top level projects, one a Swing app, the other is a set of Web Services. They both depend on the same in-house jar.

Are you using your own Maven repository? If so, the simplest option is to simply deploy the common in-house JAR and have both projects depend on the JAR, using the <dependency> element in the POM.

Nexus is a really great and easy to use repository, if you are going to use Maven in-house then you will no doubt want to run your own repository so you can actually "release" versions of each project, library JARs, etc. Repository Management with Nexus is a free book from Sonatype that details how to use it, best practices, etc.

matt b
I actually found Artifactory and got it running before I found Nexus. But I'll look at that again before going live with this.
Jim
+3  A: 

You shouldn't be adding the .jars into your projects. You should be adding JAR dependencies to your .pom files. Maven will download the .jars for you. You will have to create .pom files for each in-house .jar and add them to your maven repository (or proxy if you have one.)

Chris Nava
I think I have a good grasp of that concept. But your answer doesn't cover the second half of my question about day-to-day compilation.
Jim
In the Maven world, whenever you make a change in the CoreLibrary jar, you "release" a new version of it (you literally bump the version number up a level) and then update the POM of the dependent project's to refer to the new version. Maven handles the rest.
matt b
You may also want to read up on _SNAPSHOT versions. Using a snapshot version in your POM allows you to tell maven to get a fresh copy of the .jar (without upping the version number) each time you do a build.Be sure to remove the _SNAPSHOT for your final release.
Chris Nava
+1  A: 

Within your Development directory you would have a pom which would look something like the following:

<project>
    <groupId>yourGroup</groupId>
    <artifactId>project</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>coreLibrary</module>
        <module>swingApp</module>
        <module>webServices</module>
    </modules>
</project>

yeah, I've left out some of the other elements, so fill in whatever else you need for a complete pom.

Then, your coreLibrary, swingApp, and webServices modules would each have a pom with a parent element, and any dependencies, as follows

<project>
    <parent>
        <groupId>yourGroup</groupId>
        <artifactId>project</artifactId>
        <version>yourVersion</version>
    </parent>
    <artifactId>webServices</artifactId>
    <packaging>war</packaging>
    <version>yourVersion</version>
    <dependencies>
        <dependency>
            <groupId>yourGroup</groupId>
            <artifactId>coreLibrary</artifactId>
            <version>yourVersion</version>
        </dependency>
    </dependencies>
</project>

If you build at the root level, then it will build all 3 modules, or, even better, you could use the --also-make option to build only webServices and its dependencies (in this case coreLibrary)

mvn -am --projects webServices clean install
digitaljoel
I'm experimenting with this setup, and so far it is working well.
Jim
Good to hear. Note that the second pom sample is basically what you would have for your webServices. The swingApp would look much the same, but with a different artifactId. The coreLibrary would also have a different artifactId and wouldn't have any dependencies on any of your projects, but you probably already figured that out.
digitaljoel
Looking up more information on the also-make option, I found this http://www.sonatype.com/people/2009/10/maven-tips-and-tricks-advanced-reactor-options/This is exactly the kind of thing I am starting to do.
Jim
yeah, that's the link I pulled the also-make information from. Very helpful.
digitaljoel
+1  A: 

Technically, there are several solutions to implement this build but, depending on the coupling between these project and their life cycles, you might end up choosing one option or the other. Some questions may help to decide:

  • Who is building all these projects? A unique team? Separated teams?
  • Is there any relations between the SwingApp and the WebServices? When you build the SwingApp, does it make sense to build the WebServices? When you release the SwingApp, do you release the WebServices too? Do the SwingApp and WebServices projects always use the same version of the CoreLibrary?
  • Does it make sense to build the 3 projects together?
  • Does it make sense to build the CoreLibrary separately and have both projects depend on the produced jar?

Based on the provided informations, my understanding (which may be wrong, it's just an interpretation) is that all 3 projects are actually tightly coupled and developed in the same time, by the same people. When the core library is modified, the dependent project are rebuilt. So, I'd suggest the following multi-modules project:

my-app/           // this is the parent module, it aggregates the child modules  
|-- pom.xml       
|-- core-library  
|   `-- pom.xml   
|-- swing-app     // this module has a dependency on core-library  
|   `-- pom.xml   
`-- web-services  // this module has a dependency on core-library  
    `-- pom.xml   

The idea is to put all projects under a parent module and to use both project aggregation and project inheritance:

  • The parent project will be used to aggregate the child modules. It has a packaging of type pom and declare a <modules> element containing all 3 child modules. By doing so, the parent project now knows its modules, and if a Maven command is invoked against the parent project, that Maven command will then be executed to the parent's modules as well.
  • Each child module will declare the parent project as <parent>. This is useful to inherit common part from the parent pom
  • The swing-app and the web-services modules will have a <dependency> on core-library declared in their pom. During a multi-modules build, dependencies are use by maven to calculate the build order.

With this setup, the core-library will be build before swing-app and web-services when running Maven from the top project (this is called a multi modules build or reactor build) which seems to be the desired behavior. This seems thus equivalent to the actual situation without the messy local JARs management (with maven, dependencies are managed through a "local repository" and this is a built-in feature).

Note: If NetBeans doesn't like nested modules, it's possible to use a flat layout like this (but this is more a detail for now):

my-app/           
|-- parent
|   `-- pom.xml       
|-- core-library  
|   `-- pom.xml   
|-- swing-app     
|   `-- pom.xml   
`-- web-services  
    `-- pom.xml   

For implementation details, the Multi Module Project with Eclipse might help you to get started very fast, just skip the Eclipse specific steps. Or check out the Chapter 6. A Multi-module Project of Sonatype's Maven book for a "real" reference.

Pascal Thivent