0

How do I write simple a java main() that:

  1. Takes a maven scope name and a pom.xml file path as arguments
  2. Produces a list of Strings containing the classpath of the corresponding maven project and scope
  3. Only depends on libraries that are currently being maintained?

Motivation:

I'm trying to upgrade the dependencies of the fitnesse-maven-classpath plugin found at https://github.com/amolenaar/fitnesse-maven-classpath , which has usability issues because of its dependency on maven-embedder-3.0.4, see for example Fitnesse maven-classpath-plugin conflicting with Guava jar and Maven / Plexus ComponentLookupException - classpath nightmare? .

Simply upgrading the dependency in the plugin's pom file to maven-embedder-3.1.1 and replacing import com.sonatype.aether with import com.eclipse.aether in the java source makes the project compilable, but the tests fail with a long list of errors that starts as follows:

    Unable to parse POM file: org.codehaus.plexus.component.repository.exception.ComponentLookupException: com.google.inject.ProvisionException: Guice provision errors:

    1) No implementation for java.util.Set<org.eclipse.aether.RepositoryListener> was bound.
      while locating java.util.Set<org.eclipse.aether.RepositoryListener>
        for parameter 0 at org.eclipse.aether.internal.impl.DefaultRepositoryEventDispatcher.<init>(Unknown Source)
      while locating org.eclipse.aether.internal.impl.DefaultRepositoryEventDispatcher
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      while locating org.eclipse.aether.impl.RepositoryEventDispatcher
        for parameter 0 at org.eclipse.aether.internal.impl.DefaultMetadataResolver.<init>(Unknown Source)
      while locating org.eclipse.aether.internal.impl.DefaultMetadataResolver
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      while locating org.eclipse.aether.impl.MetadataResolver
        for parameter 0 at org.apache.maven.repository.internal.DefaultVersionResolver.<init>(Unknown Source)
      while locating org.apache.maven.repository.internal.DefaultVersionResolver
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      while locating org.eclipse.aether.impl.VersionResolver
        for parameter 0 at org.eclipse.aether.internal.impl.DefaultRepositorySystem.<init>(Unknown Source)
      while locating org.eclipse.aether.internal.impl.DefaultRepositorySystem
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      while locating org.eclipse.aether.RepositorySystem
      while locating org.apache.maven.artifact.resolver.DefaultArtifactResolver
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      while locating org.apache.maven.artifact.resolver.ArtifactResolver
      while locating org.apache.maven.repository.legacy.LegacyRepositorySystem
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      while locating org.apache.maven.repository.RepositorySystem
      while locating org.apache.maven.execution.DefaultMavenExecutionRequestPopulator
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      while locating org.apache.maven.execution.MavenExecutionRequestPopulator

    2) No implementation for java.util.Set<org.eclipse.aether.RepositoryListener> was bound.
      while locating java.util.Set<org.eclipse.aether.RepositoryListener>
        for parameter 0 at org.eclipse.aether.internal.impl.DefaultRepositoryEventDispatcher.<init>(Unknown Source)
      while locating org.eclipse.aether.internal.impl.DefaultRepositoryEventDispatcher

    ...
    etc
    ...

      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      at ClassRealm[maven, parent: ClassRealm[maven-parent, parent: null]]
      while locating org.apache.maven.execution.MavenExecutionRequestPopulator

    37 errors
        at com.google.inject.internal.InjectorImpl$3.get(InjectorImpl.java:974)
        at org.eclipse.sisu.inject.LazyBeanEntry.getValue(LazyBeanEntry.java:82)
        at org.eclipse.sisu.plexus.LazyPlexusBean.getValue(LazyPlexusBean.java:51)
        at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:260)
        ... 37 more

More specifically the plugin in essence consists of two parts: First deriving a classpath from a pom file, and second, feeding that classpath to fitnesse. The first part, classpath derivation, fails with the above error message when upgrading to maven-embedder-3.1.1, and with a less verbose message when upgrading to 3.5.4.

Is there a simple alternative for the existing implementation of the classpath derivation that only depends on modern libraries, say on https://github.com/apache/maven-dependency-plugin/tree/maven-dependency-plugin-3.1.1 ?

I'm specifically asking for the code of a main() method to make sure that I can transform in into plugin code, rather than having to assume that my code gets called from say a running mvn process that would have already computed the classpath.

Olivier
  • 118
  • 2
  • 8
  • Why do you need to get the classpath from the build? For what purpose? If this fitnessess plugin has an issue it should be fixed... – khmarbaise Jul 11 '18 at 14:33
  • @khmarbaise, the purpose is to see if I can fix the issue with the plugin. – Olivier Jul 11 '18 at 16:57
  • Than you should take a look into the plugin code and not to try to apply the classpath from outside... – khmarbaise Jul 11 '18 at 17:29
  • That's exactly what I'm doing. I narrowed down the problem to the classpath extraction part, i.e. the problem is independent of fitnesse. I don't understand the existing maven classpath extraction code, and suspect that somebody can think of a simpler implementation than the existing one, given that the desired functionality is almost provided by the maven-dependency-plugin, except for the fact that it's a command line tool. Once somebody provides me with a main(), I will rip off the main declaration and insert the body of the suggested main() method into the plugin's source code. – Olivier Jul 11 '18 at 18:07
  • @Olivier is not talking about fixing a Maven plugin, but a FitNesse plugin. – Fried Hoeben Jul 21 '18 at 11:47

1 Answers1

0

I encountered this same problem using the FitNesse maven plugin and I gave up trying to fix the problem. Instead I worked around it using some different approaches, maybe these will also work for you?

When running tests from the wiki (i.e. when I have a local FitNesse (web)server and want to press 'Test' or 'Suite' in my browser):

  • I use the plugin as-is (by placing it in the wiki's plugins folder) without problem; since the tests are run in a separate JVM they have their own classpath separate from the wiki's (which has the plugin), so versions of libraries do not conflict.
  • To create a local wiki installation without the need for Maven at all I use Maven's dependencies plugin to copy all libraries needed by my fixtures to a single folder and use FitNesse standard !path symbol to add all jars in that directory to the classpath (e.g. !path fixtures/*.jar)

To run tests on a build server, using the jUnit test runner I use Maven's failsafe plugin to run the FitNesse tests as-if they are normal jUnit tests. In my FitNesse installation the classpath plugin is available (to allow running the wiki locally), so no I do run into the problem you describe as the same JVM is used to parse the wiki files and run the tests:

  • I disable the classpath plugin in the FitNesse installation in this scenario (as it is not needed since the Maven Failsafe plugin will ensure that all dependencies are on the classpath of this JVM, so there is no need to parse a pom.xml again and add dependencies to the classpath again). I do this by setting a system property 'fitnesse.wikitext.widgets.MavenClasspathSymbolType.Disable' to 'true'. I choose to do this in my own subclass of FitNesse's jUnit runner (in Java code using System.setProperty("fitnesse.wikitext.widgets.MavenClasspathSymbolType.Disable", "true");), but this could also be configured in the pom.xml as part of Failsafe's configuration.
Fried Hoeben
  • 3,247
  • 16
  • 14