maven-pmd-plugin, maven-javadoc-plugin, maven-source-plugin

Beyond compilation and packaging, professional Maven projects usually need static code analysis, API documentation generation, and source artifact distribution. The Apache Maven ecosystem provides maven-pmd-plugin, maven-javadoc-plugin, and maven-source-plugin for these concerns respectively. This article examines each plugin’s role, frequently used goals, and typical configuration patterns.
PMD is a mature static analysis tool for Java. It inspects source code without executing it and flags potential defects such as unused variables, empty catch blocks, unnecessary object instantiation, and overly complex conditional expressions. The maven-pmd-plugin brings this capability into the Maven build lifecycle.

Common goals include:

  • pmd:pmd runs the analysis and writes report files.
  • pmd:check detects rule violations and can fail the build; it is typically bound to the verify phase.
  • pmd:cpd and pmd:cpd-check identify duplicated code.
  • pmd:report produces site reports.

A typical configuration looks like this:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-pmd-plugin</artifactId>
    <version>3.21.2</version>
    <configuration>
        <targetJdk>1.8</targetJdk>
        <rulesets>
            <ruleset>/rulesets/java/quickstart.xml</ruleset>
        </rulesets>
    </configuration>
    <executions>
        <execution>
            <id>pmd-check</id>
            <phase>verify</phase>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Usage notes:

  • rulesets can reference built-in rule sets or custom rule files stored in the project, helping teams enforce a unified standard.
  • To surface warnings without breaking the build, set <failOnViolation>false</failOnViolation>.
  • Reports are written to target/site by default and can be viewed with mvn site.

Generating API Documentation with maven-javadoc-plugin

The maven-javadoc-plugin converts Javadoc comments in source code into HTML API documentation. Libraries published to Maven Central are generally expected to ship a javadoc artifact alongside the main JAR, making this plugin a staple of open-source release workflows.

Common goals include:

  • javadoc:javadoc generates documentation into target/site/apidocs.
  • javadoc:jar creates documentation and packages it as xxx-javadoc.jar.
  • javadoc:aggregate produces consolidated documentation for multi-module projects.
  • javadoc:fix helps complete missing class and method comments.

A typical configuration looks like this:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>3.6.3</version>
    <configuration>
        <encoding>UTF-8</encoding>
        <charset>UTF-8</charset>
        <doclint>none</doclint>
    </configuration>
    <executions>
        <execution>
            <id>attach-javadocs</id>
            <goals>
                <goal>jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Usage notes:

  • Projects with Chinese comments should explicitly set UTF-8 encoding to avoid garbled output.
  • JDK 8 and later enable doclint by default; non-standard comments can break the build. Setting doclint to none relaxes this check.
  • When declared in <executions>, the jar goal binds to the package phase by default, so the documentation jar is produced automatically during the build.

Publishing Source Artifacts with maven-source-plugin

The maven-source-plugin packages project sources into xxx-sources.jar and attaches the artifact to the build. This lets consumers browse source code and step through debugging directly in their IDEs. It is also a common requirement for publishing to Maven Central.

Common goals include:

  • source:jar packages the main sources.
  • source:jar-no-fork performs the same task without forking a separate lifecycle.
  • source:test-jar packages test sources.

Why jar-no-fork is often preferred

The jar goal forks an independent lifecycle and re-executes phases from generate-sources through compile. In multi-module builds or projects that use code generation plugins, this can cause duplicate execution or unexpected failures. For goals bound to the build lifecycle, jar-no-fork is the safer choice.

A typical configuration looks like this:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>3.3.0</version>
    <executions>
        <execution>
            <id>attach-sources</id>
            <phase>verify</phase>
            <goals>
                <goal>jar-no-fork</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Collaboration and Best Practices

Together, these plugins form a complete delivery chain covering quality, documentation, and source traceability:

  • During verify, PMD enforces code quality and the source plugin attaches the sources jar.
  • During package, the javadoc plugin produces the documentation jar.
  • During deploy, the main artifact, sources jar, and javadoc jar are published to the remote repository.

Recommended engineering practices:

  • Integrate PMD checks into CI pipelines so issues surface early, before code is merged.
  • Manage plugin versions and shared configuration in a parent POM to prevent configuration drift across modules.
  • Enable all three plugins for public releases to satisfy central repository artifact integrity checks.
  • Verify plugin compatibility when upgrading the project JDK, since behavior can change between versions.

Summary

maven-pmd-plugin safeguards code quality, maven-javadoc-plugin generates API documentation, and maven-source-plugin provides traceable source packages. Their configuration is straightforward and their responsibilities are clearly separated, making them foundational tools for improving the standardization and maintainability of Maven projects. Understanding their goal semantics and lifecycle bindings helps teams produce complete, professional build artifacts and lays a solid groundwork for publishing components to external consumers.