Home Explore Blog CI



nixpkgs

2nd chunk of `doc/languages-frameworks/maven.section.md`
3539f50af57a76f90facbf825ab41ea1fcf8d24a88ca80cb0000000100001013
    # old source hash of 1.2.0 version
    hash = "sha256-US7j6tQ6mh1libeHnQdFxPGoxHzbZHqehWSgCYynKx8=";
  };

  # tests can be disabled by prefixing it with `!`
  # see Maven documentation for more details:
  # https://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html#Multiple_Formats_in_One
  mvnParameters = lib.escapeShellArgs [
    "-Dsurefire.failIfNoSpecifiedTests=false"
    "-Dtest=!JavaDecompilerTest#basicTest,!JavaDecompilerTest#patternMatchingTest"
  ];

  # old mvnHash of 1.2.0 maven dependencies
  mvnHash = "sha256-N9XC1pg6Y4sUiBWIQUf16QSXCuiAPpXEHGlgApviF4I=";
})
```
:::

### Offline build {#maven-offline-build}

By default, `buildMavenPackage` does the following:

1. Run `mvn package -Dmaven.repo.local=$out/.m2 ${mvnParameters}` in the
   `fetchedMavenDeps` [fixed-output derivation](https://nixos.org/manual/nix/stable/glossary.html#gloss-fixed-output-derivation).
2. Run `mvn package -o -nsu "-Dmaven.repo.local=$mvnDeps/.m2"
   ${mvnParameters}` again in the main derivation.

As a result, tests are run twice.
This also means that a failing test will trigger a new attempt to realise the fixed-output derivation, which in turn downloads all dependencies again.
For bigger Maven projects, this might lead to a long feedback cycle.

Use `buildOffline = true` to change the behaviour of `buildMavenPackage to the following:
1. Run `mvn de.qaware.maven:go-offline-maven-plugin:1.2.8:resolve-dependencies
   -Dmaven.repo.local=$out/.m2 ${mvnDepsParameters}` in the fixed-output derivation.
2. Run `mvn package -o -nsu "-Dmaven.repo.local=$mvnDeps/.m2"
   ${mvnParameters}` in the main derivation.

As a result, all dependencies are downloaded in step 1 and the tests are executed in step 2.
A failing test only triggers a rebuild of step 2 as it can reuse the dependencies of step 1 because they have not changed.

::: {.warning}
Test dependencies are not downloaded in step 1 and are therefore missing in
step 2 which will most probably fail the build. The `go-offline` plugin cannot
handle these so-called [dynamic dependencies](https://github.com/qaware/go-offline-maven-plugin?tab=readme-ov-file#dynamic-dependencies).
In that case you must add these dynamic dependencies manually with:
```nix
maven.buildMavenPackage rec {
  manualMvnArtifacts = [
    # add dynamic test dependencies here
    "org.apache.maven.surefire:surefire-junit-platform:3.1.2"
    "org.junit.platform:junit-platform-launcher:1.10.0"
  ];
}
```
:::

### Stable Maven plugins {#stable-maven-plugins}

Maven defines default versions for its core plugins, e.g. `maven-compiler-plugin`. If your project does not override these versions, an upgrade of Maven will change the version of the used plugins, and therefore the derivation and hash.

When `maven` is upgraded, `mvnHash` for the derivation must be updated as well: otherwise, the project will be built on the derivation of old plugins, and fail because the requested plugins are missing.

This clearly prevents automatic upgrades of Maven: a manual effort must be made throughout nixpkgs by any maintainer wishing to push the upgrades.

To make sure that your package does not add extra manual effort when upgrading Maven, explicitly define versions for all plugins. You can check if this is the case by adding the following plugin to your (parent) POM:

```xml
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-enforcer-plugin</artifactId>
  <version>3.3.0</version>
  <executions>
    <execution>
      <id>enforce-plugin-versions</id>
      <goals>
        <goal>enforce</goal>
      </goals>
      <configuration>
        <rules>
          <requirePluginVersions />
        </rules>
      </configuration>
    </execution>
  </executions>
</plugin>
```

## Manually using `mvn2nix` {#maven-mvn2nix}
::: {.warning}
This way is no longer recommended; see [](#maven-buildmavenpackage) for the simpler and preferred way.
:::

For the purposes of this example let's consider a very basic Maven project with the following `pom.xml` with a single dependency on [emoji-java](https://github.com/vdurmont/emoji-java).

Title: Maven Build Options: Offline Builds, Stable Plugins, and Manual mvn2nix (Deprecated)
Summary
This section details further configuration options for Maven builds within Nix. It explains how to perform offline builds by setting `buildOffline = true` and how to manage test dependencies when using this option. It also addresses the importance of using stable Maven plugin versions to avoid issues during Maven upgrades. Finally, it briefly mentions the deprecated method of manually using `mvn2nix`.