views:

469

answers:

2

The project is a library that contains the core library code, tests, and example code. At the end of the build process, the following archives should be created:

  • xy-1.1.0-core.jar
  • xy-1.1.0-tests.jar
  • xy-1.1.0-examples.jar

What is the best way to set this up with maven? Currently the setup is:

src
src/main/java
src/examples/java
src/test/java

Additionally, there should be a lib directory containing all dependencies. The xy-jars, the library jars, and other scripts should be packed into an release file xy-1.1.0.tar.gz.

+4  A: 

One of the big advantages of Maven (or drawbacks, depending on who you talk to) is "Convention over Configuration" - that means when you have the choice to attempt to crowbar your app into Maven, or attempt to crowbar Maven to your app - it's generally a lot easier to crowbar your app into Maven.

It's probably going to be easier to break your single "project" into two Maven projects - core and examples. Maven treats a "project" as something that creates a single artifact - aka JAR file, WAR file, EAR file, etc. (There are some exclusions to this - such as the testing jar, but we'll get to that later.) It's probably going to be easier to treat "examples" as a module, sub-project, or separate project that has a dependency on the "core" project.

Does the "tests" part contain tests for "core" only, or "core" and "examples"? If it's only core, then you'll want to move this into the core project's testing directory. If it's both, you're going to need to split it and move unit tests into the appropriate project.

You can generate a JAR of a project's test code by configuring the maven-jar-plugin as detailed in the guide to attached tests.

Maven keeps all dependencies of all programs built through Maven in the "local repository" - generally stored in many directories under %user_directory%/.m2 - you can get Maven to copy all of the dependencies of your project into a specified directory by using dependency:copy-dependencies as detailed on the dependency plugin page.

To build the final tar you're going to build an Assembly using the previous projects.

Nate
+1  A: 

Nate covered this for the most part, but I'll give concrete examples.

Here's how your directory layout should look like:

pom.xml
src/main/assembly/assembly.xml
core/pom.xml
core/src/main/java/...
core/src/test/java/...
examples/pom.xml
examples/src/main/java/...

In the base pom, you'll denote your submodules as follows:

<modules>
  <modules>core</modules>
  <modules>examples</modules>
</modules>

Assuming your base groupId is "com.company.example" and your artifactId is "xy", then your module poms will begin with the following (adjusting for names and versions, of course):

<parent>
  <groupId>com.company.example</groupId>
  <artifactId>xy</artifactId>
  <version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>com.company.example</groupId>
<artifactId>xy-core</artifactId>
<version>1.0.0-SNAPSHOT</version>

To make sure the assembly runs in the base project, include the following in your build configuration:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>2.1</version>
  <configuration>
    <descriptors>
      <descriptor>src/main/assembly/assembly.xml</descriptor>
    </descriptors>
  </configuration>
</plugin>

Also, to build a separate jar for the test classes, add this to the core/pom.xml file:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>jar</goal>
        <goal>test-jar</goal>
      </goals>
    </execution>
  </executions>
</plugin>

The assembly.xml itself will look like this:

<assembly>
  <id>assembly</id>
  <formats>
    <format>tar.gz</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <moduleSets>
    <moduleSet>
      <binaries>
        <dependencySets>
          <dependencySet>
            <outputDirectory>lib</outputDirectory>
          </dependencySet>
        </dependencySets>
        <outputDirectory>lib</outputDirectory>
      </binaries>
    </moduleSet>
  </moduleSets> 
</assembly>

I'm probably missing a few things here but that's the general idea.

toluju