ClassLoaders and org.apache.maven.model.Dependency

I am enumerating dependencies from MavenPom. These objects are of type org.apache.maven.model.Dependency, but apparently loaded in a different ClassLoader to my Java code compiled in buildSrc. I get the following exception: java.lang.NoClassDefFoundError: org/apache/maven/model/Dependency

Similar code in Groovy avoids the issue by dynamically binding the type. I do not want to do this in Java.

I don’t understand. You are saying that “I do not want to do this in Java”, yet your ‘buildSrc’ code is in Java?

No the code in question is in Java and compiled in the buildSrc subproject. At compile time org.apache.maven.model.Dependency is on the class path, but at runtime it isn’t in the class path of code from buildSrc. Nevertheless objects of this class exist, and so must be constructed under a classloader that isn’t an ancestor of the one loading code from buildSrc.

Groovy would have the same problem if I attempted to use compile time typing.

The java code looks like this:

import org.apache.maven.model.Dependency;

// …

public void editPom(Project project, MavenPom pom) {

for (Object dep: pom.getDependencies()) {

// The following attempt to use Dependency fails

Dependency dependency = (Dependency)dep;

}

}

If you can’t rearrange the class loading so that the maven classes can be used, then they should be removed from the compile time class path of buildSrc.

No, I would prefer not to use reflection (in Java) to interact with the Dependency objects. It is rather tedious. Unfortunately I don’t seem to have a choice.

Incidentally this bit of code is in Java so that it can use some other Java classes which are also in buildSrc and which I don’t want to rewrite. Groovy code in buildSrc can’t explicitly use Java code which is also in buildSrc.

You have at least two choices:

  1. Edit the POM on the XML rather than Maven API level. (The new ‘maven-publish’ plugin only supports the former.)

  2. Write the code in Groovy, without any references to Maven types. If the Groovy code needs to reference your own Java types, the easiest solution is to use Groovy/Java joint compilation (whether ‘buildSrc’ or not). For details, see the “Groovy plugin” chapter in the Gradle User Guide, and the samples in the ‘gradle-all’ distribution.

I tried joint compilation but it didn’t work. For now I have something working (using reflection). When I started this some months ago the new maven-publish plugin wasn’t ready for use. I will no doubt return to it in due course.

Could you at least remove the maven classes from the buildSrc compile time class path? Less surprising that way.

As long as the ‘maven’ plugin is still supported, I don’t think they can be removed.