Docs menu

Package managers

How Maven and Gradle work on Primcloud: wrappers, private repositories, settings files, and dependency caching.

On this page

Java on Primcloud builds with two tools: Maven and Gradle. Whichever one your repo advertises is the one that runs. Both resolve dependencies from the repositories your project configures, both cache their local dependency store between builds, and both work with the standard wrapper scripts the tools ship with.

Which tool runs#

Maven: activated by a Maven POM at the root: pom.xml, or a polyglot alternative (pom.atom, pom.clj, pom.groovy, pom.rb, pom.scala, pom.yaml, pom.yml).

Gradle: activated by build.gradle, settings.gradle, build.gradle.kts, or settings.gradle.kts at the root.

If both are present, Maven wins. Remove the Gradle files if that's not what you want.

Use the wrapper. A wrapper pins the tool version to whatever your team builds with locally, so a Primcloud build matches your machine.

  • Maven: if the wrapper (mvnw plus .mvn/wrapper/maven-wrapper.properties) is present, Primcloud uses it. If not, it provides a Maven for you. To choose that fallback version, set maven.version in system.properties:

    system.properties
    maven.version=3.9.4
    
  • Gradle: the wrapper is required. There's no fallback Gradle install. Run gradle wrapper locally and commit gradlew, gradlew.bat, and the gradle/wrapper/ directory.

Build behavior#

Maven builds run mvn clean install -DskipTests by default. That compiles your code, packages it (usually a JAR under target/), and installs the artifact into the local .m2 repository. Tests are skipped so deploys stay fast. Run them in CI, not in the build. Primcloud also writes a target/mvn-dependency-list.log recording every dependency resolved during the build, so you have a per-build record of what shipped.

Gradle builds run ./gradlew stage. The stage task isn't something Gradle provides out of the box. You define it in build.gradle to produce your runnable artifact. A minimal example for a Spring Boot app:

build.gradle
task stage(dependsOn: ['clean', 'installDist'])

Override the task name with the GRADLE_TASK environment variable if stage doesn't fit.

Both tools resolve dependencies against whatever repositories your project points at: Maven Central by default, plus anything in your settings.xml or build.gradle. Primcloud doesn't inject or override repositories, so resolution works the same on Primcloud as it does locally.

Private packages and registries#

Maven and Gradle both resolve auth for private repositories through their own config files. Hand credentials to the tool the way it already expects, and inject the secrets as environment variables.

Maven: via settings.xml. Drop a settings.xml at the repo root and Primcloud points Maven at it during the build:

settings.xml
<settings>
  <servers>
    <server>
      <id>my-private-repo</id>
      <username>${env.MY_REPO_USERNAME}</username>
      <password>${env.MY_REPO_PASSWORD}</password>
    </server>
  </servers>
</settings>

Set MY_REPO_USERNAME and MY_REPO_PASSWORD (or your own names) in the Secrets panel. Maven interpolates ${env.*} at build time.

If you'd rather not keep settings.xml at the repo root, use one of:

  • MAVEN_SETTINGS_PATH: path (relative to the repo root) to a settings.xml already in the repo.
  • MAVEN_SETTINGS_URL: an HTTPS URL Primcloud downloads and uses, handy when the settings file is generated per environment.

Set either in the Secrets panel.

Gradle: via build.gradle. Reference environment variables in your build config:

build.gradle
repositories {
  maven {
    url "https://pkgs.example.com/maven"
    credentials {
      username = System.getenv("MY_REPO_USERNAME")
      password = System.getenv("MY_REPO_PASSWORD")
    }
  }
}

Then set MY_REPO_USERNAME and MY_REPO_PASSWORD in the Secrets panel. They're available to the Gradle process at build time.

Both approaches keep credentials out of the repo. Secrets are stored encrypted on Primcloud and never appear in build logs.

Lockfiles#

Java's two build tools handle lockfiles differently.

Maven. Maven has no first-class lockfile the way npm or Cargo does. In practice, Maven builds are reproducible when the dependency graph fully constrains versions: no LATEST or RELEASE selectors, no floating ranges. The target/mvn-dependency-list.log Primcloud writes gives you a per-build audit trail of what actually resolved.

Gradle. Gradle supports dependency locking as an opt-in feature. Enable it per configuration in your build script:

build.gradle
dependencyLocking {
  lockAllConfigurations()
}

Run ./gradlew dependencies --write-locks locally to generate the gradle.lockfile files, then commit them. From then on, Gradle fails the build if a resolved version disagrees with the lockfile. This carries over to Primcloud directly, because the wrapper uses the same Gradle version.

Without a lockfile, two builds of the same commit can produce different dependency graphs if a version-range dependency publishes a new release between them. Pin exact versions in your build config when reproducibility matters.