Skip to main content

Maven and Gradle

Maven lifecycle

mvn clean install
mvn clean compile

Maven phases are cumulative: naming a phase runs it and everything before it in the same lifecycle.

PhaseRunsEffect
validateChecks the project is well formed
compilevalidate → compileCompiles src/main/java into target/classes
test… → testRuns unit tests in src/test/java, reports into target/surefire-reports
package… → packageProduces the jar or war in target/
verify… → verifyRuns integration tests and any checks bound to it
install… → installCopies the artefact into the local repository ~/.m2/repository
deploy… → deployUploads to the remote repository

clean belongs to a separate lifecycle and deletes target/. It is not part of install, which is why mvn clean install names both — mvn install on its own reuses whatever is already in target/.

Useful variations:

mvn -DskipTests package # compile tests, skip running them
mvn -Dmaven.test.skip=true package # skip compiling them too
mvn -o install # offline; fails rather than reaching the network
mvn -X install # debug output, for dependency resolution problems
mvn dependency:tree # where a transitive dependency came from
mvn versions:display-dependency-updates

-DskipTests and -Dmaven.test.skip are not interchangeable: the second skips test compilation, so it hides compile errors in test sources.

Gradle

Plugin was not found in any of the following sources

Plugin [id: 'xxx', version: 'xxx'] was not found in any of the following sources

Seen on Ubuntu while the same build works on Windows. The cause is the Snap package of Gradle, whose confinement blocks parts of plugin resolution.

Remove the Snap and install from the official distribution instead:

sudo snap remove gradle
# then install from https://gradle.org/releases/ , or use the wrapper

Better still, do not install Gradle system-wide at all. Commit the wrapper and invoke it, so every machine and CI runner uses the version the project was tested with:

./gradlew build # Linux, macOS
gradlew.bat build # Windows

Other causes of the same message, worth ruling out:

  • The plugin is not on the Gradle Plugin Portal and needs a pluginManagement block in settings.gradle naming its repository.
  • A corporate proxy or mirror is intercepting the request. --info shows which repositories were tried.
  • The version does not exist for the Gradle version in use.

Spring Boot plugin

plugins {
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
id 'java'
}

io.spring.dependency-management is what supplies the managed versions, so starter dependencies can be declared without one:

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}

Pinning an explicit version on a starter defeats the dependency management and is the usual source of mismatched Spring versions on the classpath.