RonK
RonK

Reputation: 9652

Maven project design - sharing a common project

I'm new to Maven and I'm trying to convert a few projects to work on Maven and I'm not sure what is the correct way to structure them - here is what I have:

I have a common module - named Common and two different applications that have nothing in common a part from the fact they both depend on Common. Let's call them A and B.

The dependencies between A->Common and B->Common are both for runtime and for tests - meaning that A's test classes require Common's test classes.

I tried various combinations I could think of - but non of them produced what I want. The strange thing is that my code compiles, but JUnits fail since the test classes from Common are not found in the classpath.

Should I add 2 profiles to the Common to create 2 artifacts and add 2 dependencies in A and B to both artifacts? (Is that possible?) Is there a correct way to do what I wanted? Should I restructure my code to fit Maven?

Upvotes: 6

Views: 3053

Answers (3)

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340733

This is a common maven pitfall. Test classes from an artifact aren't available when you depend on that artifact. It is actually reasonable: when you depend on Common, you depend on production classes (JAR file). Test classes are needed only for running tests and aren't even included in the final JAR.

Assuming your Common test classes contain some utility method needed for all Common tests, A and B tests, here is a suggested structure:

  • Common-test - containing common utility test classes (not test cases!) in /src/main/java (!)
  • Common depends on Common-test with <scope>test</scope>
  • A and B depend on both Common (with default scope) and Common-test (with test scope)

UML
(source: yuml.me)

Upvotes: 5

Jigar Joshi
Jigar Joshi

Reputation: 240900

You could structure it like

  • Common project
  • A project
  • B project

Now add CommonProject to <dependency> for A & B, that will make the commonproject available at compile time so build would go good,

If your A & B is or webapp archtype then you need to make sure that your dependencies are available in WEB-INF/lib so that it can get the dependencies at runtime

To make the dependencies available only at test time, you could use test scope

Upvotes: 2

Alexander Pogrebnyak
Alexander Pogrebnyak

Reputation: 45576

You have to run test-jar goal of maven-jar-plugin in your Common project.

This produces a new artifact with tests classifier, which contains all the classes and resources from src/test tree.

So, in Common add this:

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

And in A and B add this

<dependency>
  <groupId>common.group.id</groupId>
  <artifactId>Common</artifactId>
  <version>1.0</version>
  <classifier>tests</classifier>
  <scope>test</scope>
</dependency>

Note <classifier>tests</classifier> in this dependency declaration.

Upvotes: 2

Related Questions