Maven Plugins — Compiler, Surefire, Shade, and More

2 minute read

Plugins are the engine of Maven. Every action — compile, test, package — is performed by a plugin. Understanding plugins gives you full control over your build.


How Plugins Work

Plugins provide goals that bind to lifecycle phases:

Phase           Plugin                Goal
──────────────  ────────────────────  ──────────────
compile         maven-compiler-plugin compiler:compile
test            maven-surefire-plugin surefire:test
package         maven-jar-plugin      jar:jar

You configure plugins in <build><plugins>:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.13.0</version>
            <configuration>
                <!-- plugin-specific config -->
            </configuration>
        </plugin>
    </plugins>
</build>

Compiler Plugin — Java Version

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.13.0</version>
    <configuration>
        <release>21</release>  <!-- Java 21 -->
    </configuration>
</plugin>

Or via properties (simpler):

<properties>
    <maven.compiler.release>21</maven.compiler.release>
</properties>

<release> is preferred over <source> + <target> — it also sets --release for API compatibility checking.


Surefire Plugin — Running Tests

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.2.5</version>
    <configuration>
        <includes>
            <include>**/*Test.java</include>
            <include>**/*Tests.java</include>
        </includes>
        <excludes>
            <exclude>**/*IntegrationTest.java</exclude>
        </excludes>
    </configuration>
</plugin>
mvn test
# Runs: UserServiceTest.java, OrderTests.java
# Skips: UserIntegrationTest.java

Failsafe Plugin — Integration Tests

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>3.2.5</version>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>
mvn verify
# Runs *IT.java and *IntegrationTest.java files

Shade Plugin — Uber/Fat JAR

Packages your app + all dependencies into a single JAR:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.6.0</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <transformers>
                    <transformer implementation=
                        "org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>com.myapp.App</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>
mvn clean package
java -jar target/my-project-1.0.0.jar

Spring Boot Maven Plugin

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>3.3.0</version>
</plugin>
# Package as executable JAR
mvn clean package
java -jar target/my-app-1.0.0.jar

# Run directly
mvn spring-boot:run

Exec Maven Plugin — Run Java Classes

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.3.0</version>
    <configuration>
        <mainClass>com.myapp.App</mainClass>
    </configuration>
</plugin>
mvn exec:java

JaCoCo Plugin — Code Coverage

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.12</version>
    <executions>
        <execution>
            <goals><goal>prepare-agent</goal></goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals><goal>report</goal></goals>
        </execution>
    </executions>
</plugin>
mvn clean test
# Report: target/site/jacoco/index.html

Plugin Management

<pluginManagement> defines plugin versions in parent POM — children inherit without specifying version:

<!-- Parent POM -->
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <release>21</release>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

<!-- Child POM — no version needed -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <!-- version and config inherited from parent -->
        </plugin>
    </plugins>
</build>

Useful Plugins Summary

Plugin Purpose Command
maven-compiler-plugin Java version (automatic)
maven-surefire-plugin Unit tests mvn test
maven-failsafe-plugin Integration tests mvn verify
maven-shade-plugin Fat JAR mvn package
spring-boot-maven-plugin Spring Boot JAR/run mvn spring-boot:run
exec-maven-plugin Run main class mvn exec:java
jacoco-maven-plugin Code coverage mvn test
maven-enforcer-plugin Enforce rules (Java version, etc.) mvn verify
versions-maven-plugin Check for outdated deps mvn versions:display-dependency-updates

Common Mistakes

Mistake Fix
Wrong Surefire version (can’t find JUnit 5) Use Surefire 3.x for JUnit 5
Plugin in <pluginManagement> but not <plugins> <pluginManagement> only declares — child must also add to <plugins>
Shade plugin + Spring Boot plugin Use one or the other, not both
Missing <executions> for JaCoCo JaCoCo needs prepare-agent execution

Key Takeaways

  1. Plugins do all the work — compile, test, package are all plugin goals.
  2. Compiler plugin sets Java version; Surefire runs tests; Shade creates fat JARs.
  3. <pluginManagement> centralizes plugin config in parent POMs.
  4. Spring Boot plugin creates executable JARs with embedded server.
  5. Use versions:display-dependency-updates to find outdated dependencies.

What’s Next?

Next: Gradle Introduction — the alternative build tool with Groovy/Kotlin DSL, faster builds, and the Gradle wrapper.

Updated: