Maven plugin compiles fine but can't find class during execution

martin :

I am stuck with the following Maven problem.

Basically, I have two projects. Project A is a Maven plugin and project B is using it.

Project A pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>io.github.martinschneider</groupId>
  <artifactId>demo-maven-plugin</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>maven-plugin</packaging>
  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.25</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.7.25</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-plugin-api</artifactId>
      <version>3.6.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.plugin-tools</groupId>
      <artifactId>maven-plugin-annotations</artifactId>
      <version>3.6.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>

Project B pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>io.github.martinschneider</groupId>
  <artifactId>demo-project</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <build>
    <plugins>
      <plugin>
        <groupId>io.github.martinschneider</groupId>
        <artifactId>demo-maven-plugin</artifactId>
        <version>0.0.1-SNAPSHOT</version>
      </plugin>
    </plugins>
  </build>
</project>

When executing mvn demo:demo on project B, the mojo starts executing but then I get the following error:

[ERROR] Failed to execute goal my.group:my-maven-plugin:1.2.3:some-goal (default-cli) on project my-project: Execution default-cli of goal my.group:my-maven-plugin:1.2.3:some-goal failed: A required class was missing while executing io.github.martinschneider:demo-maven-plugin:0.0.1-SNAPSHOT:demo: org/slf4j/event/Level

The core message of the error is:

A required class was missing [...] : org/slf4j/event/Level

The log and stacktrace also include:

[WARNING] Error injecting: package.SomeMojo java.lang.NoClassDefFoundError: org/slf4j/event/Level

and

Caused by: java.lang.ClassNotFoundException: org.slf4j.event.Level
at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass (SelfFirstStrategy.java:50)
at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass (ClassRealm.java:271)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass (ClassRealm.java:247)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass (ClassRealm.java:239)

It boils down to org.slf4j.event.Level not being found on the classpath which is strange because it is in slf4j-api which is both an explicit and a transitive (via slf4j-core) dependency in the plugin.

However, for some reason it is not included in the class realm:

[DEBUG] Populating class realm plugin>io.martinschneider.github:demo-maven-plugin:0.0.1-SNAPSHOT
[DEBUG]   Included: io.martinschneider.github:demo-maven-plugin:0.0.1-SNAPSHOT
[DEBUG]   Included: org.slf4j:slf4j-simple:jar:1.7.25
...

slf4j-simple is in the list, slf4j-api is not.

A few lines earlier:

[DEBUG] Dependency collection stats: {ConflictMarker.analyzeTime=121223, ConflictMarker.markTime=606293, ConflictMarker.nodeCount=72, ConflictIdSorter.graphTime=74295, ConflictIdSorter.topsortTime=819750, ConflictIdSorter.conflictIdCount=45, ConflictIdSorter.conflictIdCycleCount=0, ConflictResolver.totalTime=1909563, ConflictResolver.conflictItemCount=70, DefaultDependencyCollector.collectTime=68369892, DefaultDependencyCollector.transformTime=3575054}
[DEBUG] io.martinschneider.github:demo-maven-plugin:jar:0.0.1-SNAPSHOT:
[DEBUG]    org.slf4j:slf4j-simple:jar:1.7.25:compile
[DEBUG]    org.slf4j:slf4j-api:jar:1.7.25:compile
...

Here, both slf4j-simple and slf4j-api are included.

The problem only occurs when I explicitly use the affected class org.slf4j.event.Level in my plugin code. If I remove any explicit usage of it everything works fine.

I'm using Maven 3.5.2 and Java 11.

I don't know if this is a problem with SLF4J or a more general problem with Maven or just an unlucky combination of events.

What I've tried:

  • deleted and re-populated my Maven repo (to rule out corrupted JAR files)
  • tried different versions of SLF4J
  • explicitly added slf4j-api under <pluginDepdendencies>
  • used Java 8 (instead of 11)

UPDATE I've created a demo project to reproduce this error: https://github.com/martinschneider/stackoverflow_53757567

Karol Dowbecki :

As per comment in MNG-5845 issue for similar problem:

The problem comes from the fact that we are exporting the slf4j-api artefact, thus plugins cannot use their own version but we forgot to export the content of the package org/slf4j/helpers. Thus the java.lang.ClassNotFoundException: org.slf4j.helpers.MessageFormatter

slf4j-api is one of the special dependencies exported by maven core however org.sfl4j.event package isn't exported. Looking at Maven master, currently the following packages are exported:

<!-- SLF4J -->
<exportedPackage>org.slf4j.*</exportedPackage>
<exportedPackage>org.slf4j.spi.*</exportedPackage>
<exportedPackage>org.slf4j.helpers.*</exportedPackage>

Because of above you won't be able to access classes from org.sfl4j.event package during your plugin execution. You can compile the plugin code since the compile classpath is different than runtime classpath. This can be confirmed by removing the second log statement and related import statement, the plugin will execute just fine which proves that SLF4J JARs aren't corrupted:

[INFO] ---------------< io.github.martinschneider:demo-project >---------------
[INFO] Building demo-project 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- demo-maven-plugin:0.0.1-SNAPSHOT:demo (default-cli) @ demo-project ---
[INFO] Hello world!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

You can either open a new issue in Maven project and include a new export statement or implement plugin logging with standard getLog() method as per A Simple Mojo guide:

@Mojo(name = "demo")
public class DemoMojo extends AbstractMojo {

  public void execute() throws MojoExecutionException, MojoFailureException {
    getLog().info("Hello world!");
  }

}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=36165&siteId=1