SonarQube Maven Plugin: How to Analyze Java Projects (2026 Guide)
Configure the SonarQube Maven plugin to analyze Java projects. Covers pom.xml setup, multi-module projects, JaCoCo coverage, and CI/CD.
Published:
The SonarQube Maven plugin is the most straightforward way to integrate static analysis into Java projects. Instead of installing a separate scanner binary and managing configuration files, the plugin runs directly inside your Maven build lifecycle. A single mvn sonar:sonar command compiles your code, collects test results, and uploads everything to your SonarQube server for analysis.
This guide covers the complete sonarqube maven configuration workflow - from adding the plugin to your pom.xml through multi-module project setups, JaCoCo code coverage integration, CI/CD pipeline usage, and troubleshooting the most common issues. Whether you are setting up SonarQube for a new Spring Boot application or retrofitting it into a legacy enterprise monolith, this is the reference you need.
If you are starting from scratch and need to install SonarQube first, see our complete SonarQube setup guide or our SonarQube Docker installation guide.
Prerequisites
Before configuring the SonarQube Maven plugin, ensure you have the following in place:
- Java 17 or later - required as the Maven runtime JDK (your project can still target Java 8, 11, or other versions)
- Maven 3.8 or later - the sonar-maven-plugin requires a modern Maven version
- A running SonarQube instance - either self-hosted via Docker or SonarQube Cloud
- A SonarQube authentication token - generated from your SonarQube instance under My Account, then Security, then Generate Tokens
- A Java project with a valid pom.xml - the plugin works with any Maven-based Java project
If you do not have a SonarQube instance yet, the quickest option is to run docker run -d --name sonarqube -p 9000:9000 sonarqube:lts-community and access it at http://localhost:9000.
Adding the SonarQube Maven Plugin to Your Project
The sonarqube maven plugin can be used in two ways - either by running it directly from the command line without any pom.xml changes, or by declaring it explicitly in your project’s pom.xml. The second approach is recommended for team projects and CI/CD pipelines because it locks the plugin version and keeps configuration under version control.
Option 1: Run Without pom.xml Changes
Maven can resolve the plugin at runtime from Maven Central. Simply run:
mvn clean verify sonar:sonar \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=YOUR_TOKEN
This downloads the latest version of sonar-maven-plugin automatically and runs the analysis. It works for quick evaluations but is not ideal for reproducible builds because the plugin version can change between runs.
Option 2: Declare in pom.xml (Recommended)
Add the plugin to your pom.xml under the <build><pluginManagement><plugins> section:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
</plugin>
</plugins>
</pluginManagement>
</build>
Then add your SonarQube properties in the <properties> section:
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.projectKey>my-project-key</sonar.projectKey>
<sonar.projectName>My Project</sonar.projectName>
<sonar.java.source>17</sonar.java.source>
</properties>
With this configuration committed to your repository, every developer and CI server uses the same plugin version and the same analysis properties. The only value that should remain external is the authentication token, which you pass at runtime via -Dsonar.token or an environment variable.
Important note on the groupId: older tutorials reference org.codehaus.mojo as the groupId. That version is deprecated. Always use org.sonarsource.scanner.maven - this is the actively maintained plugin published by SonarSource.
Running Your First Analysis
With the plugin configured, running the SonarQube analysis on your Java project takes a single Maven command.
The Basic Command
mvn clean verify sonar:sonar -Dsonar.token=YOUR_TOKEN
This command does the following in sequence:
- clean - removes previously compiled classes and artifacts
- verify - compiles the source code, runs unit tests, and executes any integration tests
- sonar:sonar - collects the compiled bytecode, test results, and source files, then uploads everything to the SonarQube server
The verify phase is critical. SonarQube needs compiled .class files for its Java analysis rules and test result files (typically Surefire XML reports) to calculate test coverage and test success metrics. If you skip the build and run mvn sonar:sonar alone on an uncleaned project, you may get stale or missing results.
Understanding the Analysis Output
When the mvn sonar:sonar goal runs, you will see output similar to this in your terminal:
[INFO] --- sonar-maven-plugin:4.0.0.4121:sonar (default-cli) @ my-project ---
[INFO] User cache: /home/user/.sonar/cache
[INFO] SonarQube version: 10.7.0
[INFO] Default locale: "en_US", source code encoding: "UTF-8"
[INFO] Indexing files...
[INFO] 42 files indexed
[INFO] Quality profile for java: Sonar way
[INFO] ------------- Run sensors on module my-project
[INFO] Sensor JavaSensor [java]
[INFO] Configured Java source version: 17
...
[INFO] ANALYSIS SUCCESSFUL, you can find the results at:
[INFO] http://localhost:9000/dashboard?id=my-project-key
Open the URL printed at the end to view your project dashboard in SonarQube. The dashboard shows bugs, vulnerabilities, code smells, code coverage, and duplication metrics. For a deeper dive into interpreting these results, see our SonarQube review.
Configuring SonarQube Properties in pom.xml
The sonarqube maven configuration supports dozens of properties that control how the analysis behaves. Here are the most important ones for Java projects.
Essential Properties
<properties>
<!-- Server connection -->
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.projectKey>com.example:my-project</sonar.projectKey>
<sonar.projectName>My Project</sonar.projectName>
<!-- Java configuration -->
<sonar.java.source>17</sonar.java.source>
<sonar.java.binaries>target/classes</sonar.java.binaries>
<!-- Source and test directories (usually auto-detected) -->
<sonar.sources>src/main/java</sonar.sources>
<sonar.tests>src/test/java</sonar.tests>
<!-- Encoding -->
<sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
</properties>
Most of these properties are auto-detected from your pom.xml by the Maven plugin. You typically only need to set sonar.host.url, sonar.projectKey, and sonar.java.source explicitly. The plugin reads <sourceDirectory>, <testSourceDirectory>, and <outputDirectory> from Maven’s project model automatically.
Exclusion Properties
Exclude generated code, third-party libraries, or specific packages from analysis:
<properties>
<!-- Exclude files from all analysis -->
<sonar.exclusions>
src/main/java/com/example/generated/**,
src/main/java/com/example/legacy/OldClass.java
</sonar.exclusions>
<!-- Exclude files from coverage calculation only -->
<sonar.coverage.exclusions>
src/main/java/com/example/config/**,
src/main/java/com/example/dto/**
</sonar.coverage.exclusions>
<!-- Exclude files from duplication detection only -->
<sonar.cpd.exclusions>
src/main/java/com/example/migrations/**
</sonar.cpd.exclusions>
</properties>
All exclusion patterns use Ant-style glob syntax. Double asterisks ** match any number of directories, and single asterisks * match any file name.
Multi-Module Maven Projects
Enterprise Java applications frequently use Maven multi-module structures - a parent POM that aggregates several child modules such as api, service, domain, and persistence. The sonarqube maven plugin handles this pattern natively, but there are specific configuration steps to get it right.
Parent POM Configuration
Define the plugin and shared properties in the parent pom.xml:
<project>
<groupId>com.example</groupId>
<artifactId>my-application</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>api</module>
<module>service</module>
<module>domain</module>
<module>persistence</module>
</modules>
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.projectKey>com.example:my-application</sonar.projectKey>
<sonar.projectName>My Application</sonar.projectName>
<sonar.java.source>17</sonar.java.source>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Running Multi-Module Analysis
From the parent directory, run:
mvn clean verify sonar:sonar -Dsonar.token=YOUR_TOKEN
The plugin traverses all modules in reactor order, analyzes each one, and uploads the results as a single aggregated project to SonarQube. In the SonarQube dashboard, you can drill down into each module individually while still seeing the overall project metrics at the top level.
Module-Specific Overrides
If a specific module needs different settings - for example, excluding generated code in the persistence module - add properties to that module’s pom.xml:
<!-- persistence/pom.xml -->
<properties>
<sonar.exclusions>
src/main/java/com/example/persistence/generated/**
</sonar.exclusions>
</properties>
Module-level properties override parent-level properties for that module only.
Skipping a Module
To exclude an entire module from SonarQube analysis, add this property to the module’s pom.xml:
<properties>
<sonar.skip>true</sonar.skip>
</properties>
This is useful for modules that contain only configuration, test utilities, or generated code that should not be analyzed.
Integrating JaCoCo Code Coverage with SonarQube
Code coverage is one of the most valuable metrics SonarQube tracks, and JaCoCo is the standard coverage tool for Maven-based Java projects. Integrating sonarqube jacoco maven requires adding the JaCoCo plugin to your build and ensuring the coverage report is generated before the SonarQube analysis runs.
Basic JaCoCo Setup
Add the JaCoCo Maven plugin to your pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.12</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The prepare-agent goal adds the JaCoCo agent to the JVM running your tests. The report goal generates an XML coverage file at target/site/jacoco/jacoco.xml during the verify phase. SonarQube automatically detects this file in its default location - no additional sonar.coverage.jacoco.xmlReportPaths property is needed.
Running the Full Pipeline
mvn clean verify sonar:sonar -Dsonar.token=YOUR_TOKEN
The execution order is:
clean- removes old build artifactscompile- compiles source codetest(with JaCoCo agent attached) - runs unit tests and collects coverage dataverify- generates the JaCoCo XML reportsonar:sonar- reads the JaCoCo report and uploads coverage data to SonarQube
JaCoCo in Multi-Module Projects
For sonarqube maven multi-module projects, each module generates its own JaCoCo report. SonarQube reads each module’s report automatically. However, if you have integration tests in a separate module that test classes from other modules, you need an aggregate report.
Add a dedicated reporting module to your parent POM:
<module>coverage-report</module>
Then create the coverage-report/pom.xml:
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>my-application</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>coverage-report</artifactId>
<packaging>pom</packaging>
<dependencies>
<!-- List all modules that need aggregated coverage -->
<dependency>
<groupId>com.example</groupId>
<artifactId>api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>service</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Then point SonarQube to the aggregate report from your parent POM:
<properties>
<sonar.coverage.jacoco.xmlReportPaths>
${project.basedir}/coverage-report/target/site/jacoco-aggregate/jacoco.xml
</sonar.coverage.jacoco.xmlReportPaths>
</properties>
Using SonarQube Maven Plugin in CI/CD
Running mvn sonar:sonar locally is useful during development, but the real value of sonarqube java analysis comes from automating it in your CI/CD pipeline. Every commit and pull request gets analyzed automatically, and quality gates block merges when standards are not met.
GitHub Actions
Create .github/workflows/sonarqube.yml:
name: SonarQube Analysis
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
sonarqube:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Build and Analyze
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
run: >
mvn -B clean verify sonar:sonar
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.projectKey=my-project-key
- name: Check Quality Gate
uses: sonarsource/sonarqube-quality-gate-action@v1
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
The fetch-depth: 0 is important because SonarQube needs the full Git history to calculate metrics on new code versus existing code. The quality gate action waits for the SonarQube server to process the analysis and fails the workflow if the gate does not pass.
For a more detailed walkthrough, see our guide on SonarQube with GitHub Actions.
Jenkins Pipeline
For Jenkins, add the SonarQube analysis to your Jenkinsfile:
pipeline {
agent any
tools {
maven 'Maven-3.9'
jdk 'JDK-17'
}
stages {
stage('Build and Analyze') {
steps {
withSonarQubeEnv('SonarQube') {
sh 'mvn clean verify sonar:sonar'
}
}
}
stage('Quality Gate') {
steps {
timeout(time: 5, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
}
}
The withSonarQubeEnv block injects the SonarQube server URL and token from the Jenkins global configuration, so you do not hardcode credentials in your pipeline. See our SonarQube Jenkins integration guide for detailed setup instructions including webhook configuration for quality gate callbacks.
GitLab CI
Add a SonarQube stage to your .gitlab-ci.yml:
sonarqube-analysis:
image: maven:3.9-eclipse-temurin-17
stage: test
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
- .m2/repository
script:
- >
mvn clean verify sonar:sonar
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.projectKey=$CI_PROJECT_NAME
-Dsonar.qualitygate.wait=true
-Dmaven.repo.local=.m2/repository
only:
- main
- merge_requests
The -Dsonar.qualitygate.wait=true property tells the Maven plugin to poll the SonarQube server and wait for the quality gate result, failing the build if the gate is not passed.
Pull Request Analysis
Analyzing pull requests is where SonarQube provides the most immediate developer feedback. Instead of finding issues after code is merged, developers see bugs, vulnerabilities, and code smells directly on their PR. Pull request analysis with the sonarqube maven plugin requires passing additional parameters that identify the PR.
PR Parameters
Add these parameters when running the analysis in a PR context:
mvn clean verify sonar:sonar \
-Dsonar.token=YOUR_TOKEN \
-Dsonar.pullrequest.key=42 \
-Dsonar.pullrequest.branch=feature/my-feature \
-Dsonar.pullrequest.base=main
In GitHub Actions, these values come from the event context:
- name: Analyze PR
if: github.event_name == 'pull_request'
run: >
mvn -B clean verify sonar:sonar
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.pullrequest.key=${{ github.event.pull_request.number }}
-Dsonar.pullrequest.branch=${{ github.head_ref }}
-Dsonar.pullrequest.base=${{ github.base_ref }}
Note that PR decoration - the inline comments SonarQube posts on pull requests - requires SonarQube Developer Edition or higher. The Community Edition only supports main branch analysis. For a full overview of editions and features, see our SonarQube review.
Troubleshooting Common Issues
Even with straightforward configuration, the sonarqube maven plugin can produce confusing errors. Here are the most common issues and their solutions.
”Not authorized” or 401 Errors
[ERROR] SonarQube server [http://localhost:9000] can not be reached
This usually means your token is invalid, expired, or not being passed correctly. Verify the token works by testing it with curl:
curl -u YOUR_TOKEN: http://localhost:9000/api/system/status
Note the colon after the token - SonarQube uses the token as a username with an empty password for basic auth. If you are passing the token via an environment variable in CI, ensure the variable name matches exactly what your pipeline configuration expects.
”Java heap space” or OutOfMemoryError
Large projects can exhaust the default Maven memory allocation. Increase it by setting the MAVEN_OPTS environment variable:
export MAVEN_OPTS="-Xmx2g -XX:+UseG1GC"
mvn clean verify sonar:sonar -Dsonar.token=YOUR_TOKEN
For CI pipelines, set this as an environment variable in your workflow file.
0% Code Coverage Despite Tests Passing
This is the most frequently reported issue with sonarqube jacoco maven integration. The root cause is almost always one of these:
- Missing JaCoCo
prepare-agentgoal - the agent must attach to the test JVM before tests run - Running
mvn sonar:sonarwithoutverify- the JaCoCo report is not generated until theverifyphase - Custom Surefire argLine overriding JaCoCo - if your pom.xml sets
<argLine>on the maven-surefire-plugin, it replaces the JaCoCo agent argument. Fix this by appending to it:<argLine>@{argLine} -Xmx1g</argLine> - Report path mismatch - if your JaCoCo report is not in the default location, set
sonar.coverage.jacoco.xmlReportPathsexplicitly
”SCM provider not found” Warning
[WARNING] SCM provider for this project is not supported
This warning appears when SonarQube cannot detect your version control system. It does not block analysis, but it disables blame information on issues. Ensure your project has a .git directory and that the jgit provider is available. In CI, use fetch-depth: 0 when checking out code.
Analysis Timeout in CI
If the SonarQube server takes too long to process results and the quality gate check times out, increase the timeout or check server performance:
<properties>
<sonar.qualitygate.timeout>600</sonar.qualitygate.timeout>
</properties>
This sets the timeout to 600 seconds (10 minutes). If analyses consistently take this long, consider upgrading your SonarQube server hardware or splitting a monolithic project into smaller ones.
Maven Profiles for Different Environments
Using Maven profiles lets you switch between SonarQube environments without changing your pom.xml:
<profiles>
<profile>
<id>sonar-local</id>
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
</properties>
</profile>
<profile>
<id>sonar-cloud</id>
<properties>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.organization>your-org</sonar.organization>
</properties>
</profile>
<profile>
<id>sonar-staging</id>
<properties>
<sonar.host.url>https://sonarqube-staging.internal.company.com</sonar.host.url>
</properties>
</profile>
</profiles>
Activate a profile when running the analysis:
mvn clean verify sonar:sonar -Psonar-cloud -Dsonar.token=YOUR_TOKEN
This approach keeps credentials out of your pom.xml and allows seamless switching between local development, staging, and production SonarQube instances.
Performance Optimization
For large Java codebases, the sonarqube maven plugin analysis can take significant time. Here are proven strategies to speed it up.
Cache the SonarQube scanner - the plugin downloads analysis modules on first run. In CI, cache the ~/.sonar/cache directory between builds.
Exclude non-essential files - generated code, DTO classes, and configuration classes add analysis time without providing actionable results. Use sonar.exclusions liberally.
Use incremental analysis - when analyzing branches, SonarQube only analyzes new and changed code by default. Ensure your CI checks out the full Git history so SonarQube can calculate the diff correctly.
Parallelize module builds - run Maven with -T 1C (one thread per CPU core) to build modules in parallel, reducing the total time before the SonarQube analysis phase begins:
mvn -T 1C clean verify sonar:sonar -Dsonar.token=YOUR_TOKEN
Alternative: CodeAnt AI for Java Code Analysis
While SonarQube remains the industry standard for Java static analysis, it requires significant infrastructure investment - a running server, a PostgreSQL database, token management, and Maven plugin configuration across every project. For teams that want code quality analysis without this operational overhead, CodeAnt AI offers a compelling alternative.
CodeAnt AI provides AI-powered code review at $24 to $40 per user per month. It connects directly to your GitHub, GitLab, or Bitbucket repositories and runs automated analysis on every pull request - no plugins, no self-hosted servers, no database maintenance. It detects code quality issues, security vulnerabilities, and performance problems using AI models trained on millions of code reviews.
The trade-off is clear: SonarQube gives you deep customization, self-hosted data control, and an extensive rule library with over 5,000 rules for Java alone. CodeAnt AI gives you faster setup, zero infrastructure, and AI-driven insights that go beyond pattern matching. Many teams use both - SonarQube for comprehensive rule-based analysis and CodeAnt AI for PR-level feedback that catches issues SonarQube’s static rules miss.
For more options, see our list of SonarQube alternatives.
Summary
The sonarqube maven plugin transforms Java code quality from a manual review process into an automated, enforceable standard. By adding a single plugin declaration to your pom.xml and running mvn sonar:sonar, you get comprehensive analysis of bugs, vulnerabilities, code smells, and code coverage - all reported to a central dashboard where your team can track quality trends over time.
The key takeaways from this guide:
- Use
org.sonarsource.scanner.mavenas the plugin groupId - the oldorg.codehaus.mojoversion is deprecated - Always run
mvn clean verify sonar:sonar- never skip the build and test phases before analysis - Lock the plugin version in your pom.xml - this ensures consistent behavior across all environments
- Add JaCoCo for code coverage - the
prepare-agentandreportgoals integrate seamlessly with SonarQube - Use Maven profiles - to switch between local, cloud, and staging SonarQube environments
- Automate in CI/CD - use GitHub Actions or Jenkins to run analysis on every commit and PR
For teams that find the self-hosted infrastructure overhead too heavy, SonarQube Cloud and CodeAnt AI both offer managed alternatives that eliminate server maintenance while preserving automated code quality enforcement.
Frequently Asked Questions
How do I run SonarQube analysis with Maven?
Run 'mvn clean verify sonar:sonar -Dsonar.host.url=http://localhost:9000 -Dsonar.token=YOUR_TOKEN' from your project root. The sonar:sonar goal triggers the SonarQube Scanner for Maven, which compiles the project, runs tests, and uploads the analysis results to your SonarQube server. You do not need to install a separate scanner binary because the Maven plugin handles everything automatically.
Do I need to add the SonarQube plugin to my pom.xml?
No, it is not strictly required. Maven can resolve the sonar-maven-plugin at runtime when you run 'mvn sonar:sonar' because SonarSource publishes it to Maven Central. However, adding it explicitly to your pom.xml under the build plugins section is recommended for production projects. This locks the plugin version, ensures consistent behavior across developer machines and CI servers, and makes the configuration self-documenting.
What is the correct Maven groupId for the SonarQube plugin?
The correct groupId is org.sonarsource.scanner.maven with the artifactId sonar-maven-plugin. Older tutorials may reference org.codehaus.mojo as the groupId, but that version has been deprecated since 2015. Always use the org.sonarsource.scanner.maven groupId to get the actively maintained version with the latest features and bug fixes.
How do I configure SonarQube for a Maven multi-module project?
Define the sonar-maven-plugin in the parent pom.xml under pluginManagement, and set sonar.projectKey and sonar.projectName as properties in the parent. Run 'mvn sonar:sonar' from the parent directory. The plugin automatically detects all child modules, analyzes each one, and aggregates the results into a single SonarQube project. Each module appears as a separate component within the project dashboard.
How do I integrate JaCoCo code coverage with SonarQube Maven?
Add the jacoco-maven-plugin to your pom.xml with the prepare-agent and report goals. The prepare-agent goal instruments your classes before tests run, and the report goal generates an XML coverage file at target/site/jacoco/jacoco.xml. SonarQube automatically detects this file when you run 'mvn clean verify sonar:sonar'. No additional sonar.coverage properties are needed if the report is in the default location.
Why does SonarQube show 0% code coverage even though my tests pass?
This usually means JaCoCo is not generating a coverage report before the SonarQube analysis runs. Ensure the jacoco-maven-plugin is configured with both the prepare-agent goal bound to the initialize phase and the report goal bound to the verify phase. Run 'mvn clean verify sonar:sonar' instead of 'mvn clean sonar:sonar' so that tests actually execute and JaCoCo generates the XML report before the scanner reads it.
Can I use SonarQube Maven plugin with SonarQube Cloud?
Yes. Replace the sonar.host.url with https://sonarcloud.io and set sonar.organization to your SonarQube Cloud organization key. You also need to set sonar.token to a token generated in your SonarQube Cloud account. The command becomes 'mvn sonar:sonar -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=your-org -Dsonar.token=YOUR_TOKEN'. Everything else works the same as with a self-hosted instance.
How do I exclude files or directories from SonarQube Maven analysis?
Set the sonar.exclusions property in your pom.xml or on the command line. Use Ant-style glob patterns such as 'src/main/java/com/example/generated/**' to exclude generated code. For test exclusions in coverage calculations, use sonar.coverage.exclusions. You can also use sonar.test.exclusions to exclude test files from analysis. Multiple patterns are separated by commas.
What Java version does the SonarQube Maven plugin require?
The SonarQube Maven plugin version 4.0 and later requires Java 17 as the minimum runtime version. This is the Java version used to run Maven itself, not the Java version your project targets. Your project can still compile to Java 8, 11, or any other version - set sonar.java.source to your project's target version so SonarQube applies the correct analysis rules.
How do I pass SonarQube properties in Maven without modifying pom.xml?
Pass properties as command-line arguments using the -D flag. For example, 'mvn sonar:sonar -Dsonar.host.url=http://localhost:9000 -Dsonar.token=YOUR_TOKEN -Dsonar.projectKey=my-project'. You can also set them in a Maven settings.xml file under an active profile, or use environment variables with the sonar-maven-plugin. Command-line properties override pom.xml properties.
How do I analyze pull requests with SonarQube Maven plugin?
Pass pull request parameters to the Maven command - 'mvn sonar:sonar -Dsonar.pullrequest.key=PR_NUMBER -Dsonar.pullrequest.branch=FEATURE_BRANCH -Dsonar.pullrequest.base=main'. This requires SonarQube Developer Edition or higher, or SonarQube Cloud. The analysis results appear as PR decoration with inline comments on the pull request rather than updating the main branch analysis.
Is there a simpler alternative to SonarQube for Java code analysis?
Yes. CodeAnt AI offers AI-powered code review at $24 to $40 per user per month with no self-hosted infrastructure to manage. It connects directly to your GitHub, GitLab, or Bitbucket repository and provides automated code quality analysis on pull requests. For teams that want Java code analysis without the overhead of running a SonarQube server, database, and Maven plugin configuration, CodeAnt AI is a lightweight alternative.
Explore More
Tool Reviews
Related Articles
Free Newsletter
Stay ahead with AI dev tools
Weekly insights on AI code review, static analysis, and developer productivity. No spam, unsubscribe anytime.
Join developers getting weekly AI tool insights.
Related Articles
Codacy GitHub Integration: Complete Setup and Configuration Guide
Learn how to integrate Codacy with GitHub step by step. Covers GitHub App install, PR analysis, quality gates, coverage reports, and config.
March 13, 2026
how-toCodacy GitLab Integration: Setup and Configuration Guide (2026)
Set up Codacy with GitLab step by step. Covers OAuth, project import, MR analysis, quality gates, coverage reporting, and GitLab CI config.
March 13, 2026
how-toHow to Set Up Codacy with Jenkins for Automated Review
Set up Codacy with Jenkins for automated code review. Covers plugin setup, Jenkinsfile config, quality gates, coverage, and multibranch pipelines.
March 13, 2026
SonarQube Review
CodeAnt AI Review