Maven Basics

From OkapiWiki

Jump to: navigation, search

Maven is the build and dependency management tool used for the Okapi Framework. There is plenty of documentation scattered across the web. This page will simply provide links to the most pertinent documentation and highlight basic operations.

Contents

Basic Project Design

The recommended maven project structure is to have a parent-child pom relationship. There are pom type projects, jar type projects, war type projects, ear type project, etc...

The POM projects do not package any code and are used mostly for common configuration and organization/hierarchy of modules.

Okapi will have a pom in the project root which all of the other modules should inherit from (this allows each module to share similar configurations with out explicitly declaring them in each project pom - code coverage, site, junit, common OSGi config, etc...)

Additional information on Parent-child relationships can be found here and on Project Inheritance can be found here.

Okapi uses a hybrid approach of using both a multi-module and inheritance model.

A basic maven project is structured according to set guidelines. Tests for a project are included in the same module. Item in the resources directory are included in the classpath or artifact (test->resources are only included while running tests).

Project structure:

pom.xml   
META-INF/MANIFEST.MF
src
   main
      java
      resources
   test
      java
      resources

Here is an example of a pom file (of type POM) that contains the pointers to the modules and produces no artifacts:

<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">
   <parent>
      <artifactId>build-okapi</artifactId>
      <groupId>net.sf.okapi</groupId>
      <version>1.0.0</version>
   </parent>
   <artifactId>build-common</artifactId>
   <packaging>pom</packaging>
   <modelVersion>4.0.0</modelVersion>
   <name>Okapi Common Build</name>
   <modules>
       <module>common</module>
       <module>filters</module>
       <module>pipeline</module>
       <module>ui</module>
       <module>ui.filters</module>
   </modules>
</project>

Here is an example of a POM using the above parent POM:

<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">
   <parent>
      <artifactId>build-common</artifactId>
      <groupId>net.sf.okapi</groupId>
      <version>1.0.0</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>common.pipeline</artifactId>
   <name>Okapi Pipeline</name>
   <dependencies>
      <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>common.filters</artifactId>
        <version>${project.version}</version>
      </dependency>
   </dependencies>
   <build>     
     <plugins>
         <plugin>
           <artifactId>maven-jar-plugin</artifactId>
           <configuration>
              <!--All JAR projects will have this same configuration -->
              <!-- This projects generated JAR will look like: net.sf.okapi.common.pipeline-1.0.0.jar -->
              <finalName>${pom.groupId}.${pom.artifactId}-${pom.version}</finalName>
           </configuration>
         </plugin>
     </plugins>
  </build>
</project>

Dependencies

A maven module is identified by group, artifact and version id. The unique combination of these represent a module/project and provides the structure for storing and retrieval of artifacts and dependencies from local and remote repositories.

See also: http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

Testing

Test Modules

It is possible to have a module that is used exclusively for shared test utilities. Configuring this project to be a test jar is as simple as adding the following to to your pom:

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

The above configuration assumes there is code in the src/test/java directory which will then be used by other modules. It is ok to have releasable code in the src/main/java directory but this code will not be included in the test jar. To use this as a dependency of tests from another project, simply add the following:

<dependency>
   <groupId>the.group.id</groupId>
   <artifactId>the-artifact</artifactId>
   <scope>test</scope>
   <classifier>tests</classifier>
   <version>the-version-number</version>
</dependency>

Unit Tests

If code can be related to a tree, then unit tests are generally written against the leaf nodes of that tree. However, if unit tests were only written against the leaf nodes, then that would mean a lot of code isn't getting tested (or covered). When testing non-leaf node methods, then it is generally a good idea to stub or mock out portions of the object graph such that you can focus on testing the code in the given method.

Unit tests should be extremely fast for the following reasons:

Generally, it is frowned on for a test to require access to something outside of the code base (database, file system ...). The reason behind this is to keep the unit tests as fast as possible. Personally, I like to be able to run all unit tests within one, maybe two, minutes.

All unit tests for a given module should be self-contained inside the module itself. The src/test/java directory is the place where these tests should go. This has several advantages. One of which is that the same package can be used, making testing protected or default methods much easier. In other words, please do not add a "tests" to the package structure.

Integration Tests

For now, it is recommended that we place all integration tests in a separate module and that module should not contain any code outside of the tests themselves. There should be one integration tests module for every major directory. For example, the steps directory would have a single integration tests module.

The project structure for an integration test module would look something like the following:

okapi
   steps
      integration-tests
         src
            test
               java
               resources

Notice how there are no src/main/java directories and therefore no shippable code for that module.

Telling Maven to Download Sources and JavaDoc

mvn dependency:sources
mvn dependency:resolve -Dclassifier=javadoc

Basic Maven Commands

mvn clean - Removes compiled code, resources and artifacts from target directory.

mvn site - Generates the html site for the project - reports, documentation, etc.

mvn compile - Compiles the project source code.

mvn package - Bundles the compiled source code and resources into desired packaging (jar, war, etc..)

mvn install - Installs the packaged artifact into the local repository - essential for integration tests.

mvn test - Executes unit tests for project(s).

mvn verify -P integration - Executes integration and unit tests for project(s).

mvn dependency:resolve - Shows a flat list of what will be included in the class path (including transitive dependencies).

mvn dependency:tree - Shows a hierarchical list of what will be included in the class path (including transitive dependencies).

mvn dependency:sources - Downloads the source code for all libraries that have one.

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox