Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to exclude a Maven test-scoped dependency from Eclipse (but keep it in the path for unit tests)

I am having some problems getting Eclipse to honour a test-scoped Maven dependency - it is showing up on the build path and messing with eclipse's compilation / javadoc resolution.

An example with Java EE libs

I have been using the javaee-api-6.0 library to compile my Java EE application against.

However, for unit testing purposes, I wanted to have access to more than just the api - I needed an implementation. So I included the embedded glassfish libs with a test scope like so:

<repositories>
    <repository>
        <id>glassfish-extras-repository</id>
        <url>http://download.java.net/maven/glassfish/org/glassfish/extras</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>org.glassfish.extras</groupId>
        <artifactId>glassfish-embedded-all</artifactId>
        <version>3.1.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>6.0</version>
        <scope>compile</scope>
        <type>jar</type>
    </dependency>
</dependencies>

Works as expected with Maven

From my understanding, because of the <scope>test</scope> of the glassfish dependency, it will not be included in the regular compile phase.

Because both dependencies would be included in the test-compile phase, I was sure to place the glassfish dependency before the javaee-api dependency so that the former would be used in preference to the latter when compiling the test classes. And so, when using just Maven to build, this configuration is not a problem.

Does not work as expected within Eclipse

However, when using m2e and Eclipse, the glassfish dependency is listed in my build path:

dependency listed on build path

Because the glassfish dependency is listed before the java-ee-api dependency, it appears that Eclipse is using the wrong lib (glassfish, instead of the java-ee-api) to validate / compile / look up javadocs. (Actually, I am not 100% sure that compilation is using the wrong lib - it depends on whether under the hood Eclipse is using Maven to perform the compilation used when validating code, and I don't know if it is or not - but the javadoc lookup is definitely referencing the wrong lib)

The Question

How can I stop Eclipse from using the glassfish lib except for when running unit tests? I want to ensure my compilation / javadoc lookups are ocurring on the api, not a particular implementation of that api.

like image 315
Ryan Bennetts Avatar asked Feb 24 '12 07:02

Ryan Bennetts


3 Answers

It's been a while since I first posted this question, but:

How can I stop Eclipse from using the glassfish lib except for when running unit tests?

You can't. Eclipse is tied to the concept of one build path per project and m2e/m2e-wtp cannot (or will not) overcome this limitation, as described in the following bug:

Scope of dependencies has no effect on Eclipse compilation

Update 08-June-2016

With the release of JEE7, the javaee-api jar file now contains real usable class files. This means it can be used in tests, and I need not specify the glassfish-embedded-all jar file before it in the pom file.

So now that eclipse is pulling source and javadoc from the right jar file (ie javaee-api and not glassfish-embedded-all) I don't care as much that the test-scoped glassfish-embedded-all is still on the classpath in Eclipse.

It's not a solution to the question I originally proposed, but it is a solution to the underlying problem I was experiencing at the time. Perhaps it'll help someone else, too.

like image 151
Ryan Bennetts Avatar answered Oct 26 '22 03:10

Ryan Bennetts


I have been struggling with this problem as well and finally found a solution. You have installed the m2e plugin but you also need the m2e wtp connector, which is not installed by default. Depending on your m2e version this is accomplished differently. For the latest version, under 'Preferences' -> 'Maven' -> 'Discovery'. Click 'Open Catalog'. Select the M2E - WTP connector.

After installation, right-click your project and select 'Maven' -> 'Update Project Configuration...'

Your pom.xml should look like this:

<dependency>
    <groupId>org.glassfish.main.extras</groupId>
    <artifactId>glassfish-embedded-all</artifactId>
    <version>3.1.2.2</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
</dependency>

Eclipse should deploy happily, unit tests should execute in eclipse, and maven on the command-line should be agreeable as well.

Hope this helps.

like image 22
J. Andrew Thompson Avatar answered Oct 26 '22 03:10

J. Andrew Thompson


Maybe it works if you configure the surefire-plugin to

  • exclude the API depedency (which is included as a project dependency) and
  • include the glasfish dependency (do not include it to the project dependencies)

like this:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.12</version>
            <configuration>
                <classpathDependencyExcludes>
                    <classpathDependencyExclude>javax:javaee-api
                    </classpathDependencyExclude>
                </classpathDependencyExcludes>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.glassfish.extras</groupId>
                    <artifactId>glassfish-embedded-all</artifactId>
                    <version>3.1.1</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

Have a look at the Configuring the Classpath part of the surefire plugin (the plugin that executes the tests) site.


From the documentation (outer exclude element name AND inner exclude element name with 's')

     <classpathDependencyExcludes>
        <classpathDependencyExcludes>org.apache.commons:commons-email</classpathDependencyExcludes>
      </classpathDependencyExcludes>

but I suppose it should be (only outer element name with 's'):

     <classpathDependencyExcludes>
        <classpathDependencyExclude>org.apache.commons:commons-email</classpathDependencyExclude>
      </classpathDependencyExcludes>
like image 27
FrVaBe Avatar answered Oct 26 '22 04:10

FrVaBe