5 Replies Latest reply on May 28, 2013 10:53 AM by richard.emerson

    MavenImporter: how to exclude test-scoped dependencies?

    richard.emerson

      Hi,

       

      I've just started using the new MavenImporter in 2.0.0-beta-1 and it looks pretty awesome!

       

      I'm building a WAR for some Arquillian client-only tests, so the WAR doesn't need any of the test-scoped dependendencies.  I do this:

       

        @Deployment(testable = false)

        public static WebArchive createDeployment()

        {

          return ShrinkWrap.create(MavenImporter.class)

            .loadPomFromFile("pom.xml")

            .importBuildOutput(new AcceptScopesStrategy(ScopeType.COMPILE, ScopeType.RUNTIME))

            .as(WebArchive.class);

        }

       

      but the resulting WAR still contains all the test-scoped dependencies.  Checking the POM with Maven shows that (for example) Arquillian, Shrinkwrap, JUnit etc are definitely test-scoped, but they still appear in the resulting WAR.  The tests still pass, but building and deploying the much bigger WAR takes a long time.

       

      By tracing through this with a debugger I can see that when the POM is compiled, dependencies of all scopes are calculated.  The ScopeFilter from my supplied strategy is not applied until much later (is this due to some Maven reason?).

       

      When the tree of all dependencies has finally been built, in Aether's DefaultRepositorySystem.resolveDependencies(), then a FilteringDependencyVisitor that wraps the correct ScopeFilter is applied to the tree -- but it seems to make no difference: all the dependencies in the tree are returned as results.  I could not figure out why

       

      Any guesses, anyone?

       

      Many thanks,

      Richard

        • 1. Re: MavenImporter: how to exclude test-scoped dependencies?
          richard.emerson

          And a related question: will the MavenImporter automatically find and use my $HOME/.m2/settings.xml, and use the local Maven repository on my machine?  If not, how can I make it do that?

           

          Thanks again,

          Richard

          • 2. Re: MavenImporter: how to exclude test-scoped dependencies?
            richard.emerson

            I figured out that I was doing it wrong.  I was looking at Maven's dependency scopes, when what I really wanted was all the dependencies on the Maven project's runtime classpath.  The runtime classpath is calculated based on the scopes of the dependencies plus one or two other things.

             

            Shrinkwrap doesn't have a ready-made MavenResolutionStrategy that only chooses dependencies which would be on the runtime classpath, but I wrote a simple one like this:

             

            {code}

            public class RuntimeClasspathOnlyStrategy implements MavenResolutionStrategy, MavenResolutionFilter

            {

                private final MavenResolutionFilter[] resolutionFilters;

             

                public RuntimeClasspathOnlyStrategy()

                {

                    this.resolutionFilters = new MavenResolutionFilter[] { this };

                }

             

                @Override

                public MavenResolutionFilter[] getPreResolutionFilters()

                {

                    return resolutionFilters;

                }

             

                @Override

                public MavenResolutionFilter[] getResolutionFilters()

                {

                    return resolutionFilters;

                }

             

                @Override

                public TransitiveExclusionPolicy getTransitiveExclusionPolicy()

                {

                    return DefaultTransitiveExclusionPolicy.INSTANCE;

                }

             

                @Override

                public boolean accepts(MavenDependency dependency, List<MavenDependency> dependenciesForResolution)

                {

                    return PackagingType.JAR.equals(dependency.getPackaging())

                        && ( ScopeType.COMPILE.equals(dependency.getScope()) || ScopeType.RUNTIME.equals(dependency.getScope()) );

                }

            }

            {code}

             

            Now, I think this might actually be too simple: there might be some subtle rules in Maven about resolving conflicts which I don't really understand (see for example Aether's JavaEffectiveScopeCalculator).

             

            Also, my strategy filters dependencies pre-resolution, which makes building the war much quicker, but might be wrong for some other subtle reason.  The Shrinkwrap AcceptScopesStrategy doesn't do any pre-resolution filtering, but I don't know why.

             

            Anyway it seems to produce the right result in my project for now - maybe other people will find it useful.  If I've done this wrong, please let me know!

             

            Cheers.

            • 3. Re: MavenImporter: how to exclude test-scoped dependencies?
              kpiwko

              Hi Richard,

               

              I think that .importBuildOutput(new AcceptScopesStrategy(ScopeType.COMPILE, ScopeType.RUNTIME)) should work exactly the way you intend to use it. MavenImporter should use all scopes that are relevant to get the compilation and then include dependencies only from scopes you requested.

               

              Therefore, I've filled a bug at https://issues.jboss.org/browse/SHRINKRES-112.

               

              As for the settings.xml question, it MavenImporter will find ~/.m2/settings.xml by default and honor <localRepository> from there.

               

              As we do not have support to set settings.xml programatically yet (https://issues.jboss.org/browse/SHRINKRES-97), you can use following workaround meanwhile:

               

              System.setProperty(MavenSettingsBuilder.ALT_USER_SETTINGS_XML_LOCATION, "path/to/settings.xml");

               

              or

               

              System.setProperty(MavenSettingsBuilder.ALT_LOCAL_REPOSITORY_LOCATION, "path/to/local/repo);

               

              depending on what you exactly need.

               

              Keep testing,

               

              Karel

              • 4. Re: MavenImporter: how to exclude test-scoped dependencies?
                kpiwko

                API proposal changes discussed here:

                https://community.jboss.org/thread/228683

                 

                Richard, note you should be be able to exclude test scoped dependencies from beta-3 forward, there was a bug in previous version.

                • 5. Re: MavenImporter: how to exclude test-scoped dependencies?
                  richard.emerson

                  Awesome, thank you very much for the update Karel!