Search code examples
javamavenoptaplannermaven-enforcer-plugin

Why am I getting a banned dependency error in one of the submodule in Maven project?


I have a maven with several modules setup like this:

- backend
- frontend
- benchmark
pom.xml

When I build the project, I get this error when building the benchmark module:

[WARNING] Rule 0: org.apache.maven.plugins.enforcer.BannedDependencies failed with message:
Found Banned Dependency: commons-logging:commons-logging:jar:1.2
Use 'mvn dependency:tree' to locate the source of the banned dependencies.

I've run mvn dependency:tree and from what I can tell, its because the sendgrid-java package being used in the backend module contains the commons-logging dependency. It's a managed dependency so its declared in the root pom.xml file and then used in backend module.

I'm unable to understand why its giving me this banned dependency error. I've looked at all my pom.xml files, and there's no mention of any banned dependencies.

I can solve this problem by putting <enforcer.skip>true</enforcer.skip> in the pom.xml for the benchmark module, but I want to know why this problem is being caused? Where is maven getting the banned dependency from?

Here's my root pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.optaplanner</groupId>
    <artifactId>optaplanner-build-parent</artifactId>
    <version>8.24.1.Final</version>
    <relativePath/>
  </parent>

  <groupId>org.optaweb.employeerostering</groupId>
  <artifactId>optaweb-employee-rostering</artifactId>
  <packaging>pom</packaging>

  <name>OptaWeb Employee Rostering as a Service Parent</name>
  <description>
    OptaWeb Employee Rostering as a Service with OptaPlanner on OpenShift 4.
    This project is no longer maintained.
  </description>
  <url>https://www.optaplanner.org</url>
  <inceptionYear>2017</inceptionYear>

  <repositories>
    <!-- Bootstrap repository to locate the parent pom when the parent pom has not been build locally. -->
    <repository>
      <id>jboss-public-repository-group</id>
      <name>JBoss Public Repository Group</name>
      <url>https://repository.jboss.org/nexus/content/groups/public/</url>
      <layout>default</layout>
      <releases>
        <enabled>true</enabled>
        <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
        <enabled>true</enabled>
        <updatePolicy>daily</updatePolicy>
      </snapshots>
    </repository>
  </repositories>

  <properties>
    <!-- Define JaCoCo agent argLine property to avoid Surefire failure when JaCoCo is not enabled. -->
    <jacoco.agent.argLine/>

    <sonar.projectKey>optaweb-employee-rostering</sonar.projectKey>
    <sonar.moduleKey>${project.artifactId}</sonar.moduleKey>

    <version.frontend-maven-plugin>1.12.1</version.frontend-maven-plugin>
    <version.node>v16.2.0</version.node>
    <version.npm>7.15.1</version.npm>
    <version.org.apache.poi>4.1.2</version.org.apache.poi>
  </properties>

  <modules>
    <module>optaweb-employee-rostering-frontend</module>
    <module>optaweb-employee-rostering-backend</module>
    <module>optaweb-employee-rostering-benchmark</module>
    <module>optaweb-employee-rostering-docs</module>
    <module>optaweb-employee-rostering-distribution</module>
    <module>optaweb-employee-rostering-standalone</module>
  </modules>

  <dependencyManagement>
    <dependencies>
      <!-- Internal modules -->
      <dependency>
        <groupId>org.optaweb.employeerostering</groupId>
        <artifactId>optaweb-employee-rostering-frontend</artifactId>
        <type>zip</type>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>org.optaweb.employeerostering</groupId>
        <artifactId>optaweb-employee-rostering-frontend</artifactId>
        <type>pom</type>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>org.optaweb.employeerostering</groupId>
        <artifactId>optaweb-employee-rostering-backend</artifactId>
        <type>jar</type>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>org.optaweb.employeerostering</groupId>
        <artifactId>optaweb-employee-rostering-backend</artifactId>
        <classifier>exec</classifier>
        <type>jar</type>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>org.optaweb.employeerostering</groupId>
        <artifactId>optaweb-employee-rostering-docs</artifactId>
        <type>zip</type>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>org.optaweb.employeerostering</groupId>
        <artifactId>optaweb-employee-rostering-standalone</artifactId>
        <classifier>quarkus-app</classifier>
        <type>zip</type>
        <version>${project.version}</version>
      </dependency>

      <!-- BOMs -->
      <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-bom</artifactId>
        <version>${version.io.quarkus}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <!-- Excel -->
      <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>${version.org.apache.poi}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>${version.org.apache.poi}</version>
      </dependency>

      <dependency>
        <groupId>org.jacoco</groupId>
        <artifactId>org.jacoco.agent</artifactId>
        <classifier>runtime</classifier>
        <version>${version.jacoco.plugin}</version>
        <scope>test</scope>
      </dependency>

      <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>auth0</artifactId>
        <version>2.0.0</version>
      </dependency>

      <dependency>
        <groupId>com.sendgrid</groupId>
        <artifactId>sendgrid-java</artifactId>
        <version>4.7.3</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-dependency-plugin</artifactId>
          <executions>
            <execution>
              <id>analyze-only</id>
              <phase>none</phase>
            </execution>
          </executions>
        </plugin>
        <plugin>
          <groupId>com.github.eirslett</groupId>
          <artifactId>frontend-maven-plugin</artifactId>
          <version>${version.frontend-maven-plugin}</version>
          <configuration>
            <nodeVersion>${version.node}</nodeVersion>
            <npmVersion>${version.npm}</npmVersion>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

  <profiles>
    <!-- TODO: Remove me when Quarkus upgraded to 1.13 -->
    <!-- See https://github.com/quarkusio/quarkus/pull/14384 for details -->
    <profile>
      <!--
        TODO: For moving the coverage measurement from Travis to Jenkins, add the repository name to
        SONARCLOUD_ENABLED_REPOSITORIES in
        https://github.com/kiegroup/kie-jenkins-scripts/blob/main/job-dsls/jobs/pr_jobs.groovy
      -->
      <id>run-code-coverage</id>
      <dependencies>
        <dependency>
          <groupId>org.jacoco</groupId>
          <artifactId>org.jacoco.agent</artifactId>
          <classifier>runtime</classifier>
          <scope>test</scope>
        </dependency>
      </dependencies>
      <build>
        <pluginManagement>
          <plugins>
            <plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <configuration>
                <argLine/>
                <systemPropertyVariables>
                  <jacoco-agent.destfile>${project.build.directory}/jacoco.exec</jacoco-agent.destfile>
                  <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                  <maven.home>${maven.home}</maven.home>
                </systemPropertyVariables>
              </configuration>
            </plugin>
          </plugins>
        </pluginManagement>
        <plugins>
          <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>jacoco-prepare-agent</id>
                <goals>
                  <goal>prepare-agent</goal>
                </goals>
                <configuration>
                  <skip>true</skip>
                </configuration>
              </execution>
              <execution>
                <id>instrument</id>
                <goals>
                  <goal>instrument</goal>
                </goals>
              </execution>
              <execution>
                <id>restore</id>
                <goals>
                  <goal>restore-instrumented-classes</goal>
                </goals>
              </execution>
              <execution>
                <id>report</id>
                <goals>
                  <goal>report</goal>
                </goals>
                <configuration>
                  <dataFile>${project.build.directory}/jacoco.exec</dataFile>
                  <outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
                </configuration>
              </execution>
              <execution>
                <id>merge-results</id>
                <phase>verify</phase>
                <goals>
                  <goal>merge</goal>
                </goals>
                <configuration>
                  <fileSets>
                    <fileSet>
                      <directory>${project.build.directory}</directory>
                      <includes>
                        <include>*.exec</include>
                      </includes>
                    </fileSet>
                    <fileSet>
                      <directory>${project.root.dir}/target</directory>
                      <includes>
                        <include>*.exec</include>
                      </includes>
                    </fileSet>
                  </fileSets>
                  <destFile>${jacoco.exec.file}</destFile>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>

I've tried searching in all the pom.xml files but there's no settings for the enforcer plugin. My guess is that there is some default configuration causing all this, but I'm not sure what it is.


Solution

  • Maven Enforcer Plugin provides goals to control certain environmental constraints such as Maven version, JDK version and OS family along with many more built-in rules and user created rules.

    Any company, community can create custom rules by their own standards, observations and so on.

    In that certain case OptaPlanner supports only SLF4J + Logback, more precisely they forbid all other logging frameworks (eg. commons-logging, log4j).

    So exclude that commons-logging dependency if it is possible and use org.slf4j:jcl-over-slf4j.

    Otherwise only in backend module disable the Enforcer Plugin.

    Finally you can override only that certain execution of enforcer plugin

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <executions>
                    <execution>
                        <id>ban-forbidden-dependencies</id>
                        <phase/>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>