Home Explore Blog CI



nixpkgs

1st chunk of `doc/languages-frameworks/maven.section.md`
45b5631690134726032b8e84ce53f0f5c4f3614541e200f90000000100000fc1
# Maven {#maven}

Maven is a well-known build tool for the Java ecosystem however it has some challenges when integrating into the Nix build system.

The following provides a list of common patterns with how to package a Maven project (or any JVM language that can export to Maven) as a Nix package.

## Building a package using `maven.buildMavenPackage` {#maven-buildmavenpackage}

Consider the following package:

```nix
{
  lib,
  fetchFromGitHub,
  jre,
  makeWrapper,
  maven,
}:

maven.buildMavenPackage rec {
  pname = "jd-cli";
  version = "1.2.1";

  src = fetchFromGitHub {
    owner = "intoolswetrust";
    repo = "jd-cli";
    tag = "jd-cli-${version}";
    hash = "sha256-rRttA5H0A0c44loBzbKH7Waoted3IsOgxGCD2VM0U/Q=";
  };

  mvnHash = "sha256-kLpjMj05uC94/5vGMwMlFzLKNFOKeyNvq/vmB6pHTAo=";

  nativeBuildInputs = [ makeWrapper ];

  installPhase = ''
    runHook preInstall

    mkdir -p $out/bin $out/share/jd-cli
    install -Dm644 jd-cli/target/jd-cli.jar $out/share/jd-cli

    makeWrapper ${jre}/bin/java $out/bin/jd-cli \
      --add-flags "-jar $out/share/jd-cli/jd-cli.jar"

    runHook postInstall
  '';

  meta = {
    description = "Simple command line wrapper around JD Core Java Decompiler project";
    homepage = "https://github.com/intoolswetrust/jd-cli";
    license = lib.licenses.gpl3Plus;
    maintainers = with lib.maintainers; [ majiir ];
  };
}
```

This package calls `maven.buildMavenPackage` to do its work. The primary difference from `stdenv.mkDerivation` is the `mvnHash` variable, which is a hash of all of the Maven dependencies.

::: {.tip}
After setting `maven.buildMavenPackage`, we then do standard Java `.jar` installation by saving the `.jar` to `$out/share/java` and then making a wrapper which allows executing that file; see [](#sec-language-java) for additional generic information about packaging Java applications.
:::

### Overriding Maven package attributes {#maven-overriding-package-attributes}

```
overrideMavenAttrs :: (AttrSet -> Derivation) | ((AttrSet -> Attrset) -> Derivation) -> Derivation
```

The output of `buildMavenPackage` has an `overrideMavenAttrs` attribute, which is a function that takes either
- any subset of the attributes that can be passed to `buildMavenPackage`

  or
- a function that takes the argument passed to the previous invocation of `buildMavenPackage` (conventionally called `old`) and returns an attribute set that can be passed to `buildMavenPackage`

and returns a derivation that builds a Maven package based on the old and new arguments merged.

This is similar to [](#sec-pkg-overrideAttrs), but notably does not allow accessing the final value of the argument to `buildMavenPackage`.

:::{.example}
### `overrideMavenAttrs` Example

Use `overrideMavenAttrs` to build `jd-cli` version 1.2.0 and disable some flaky test:

```nix
jd-cli.overrideMavenAttrs (old: rec {
  version = "1.2.0";
  src = fetchFromGitHub {
    owner = old.src.owner;
    repo = old.src.repo;
    rev = "${old.pname}-${version}";
    # 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.

Title: Packaging Maven Projects with Nix
Summary
This section discusses how to package Maven projects within the Nix build system, addressing challenges and outlining common patterns. It specifically focuses on using `maven.buildMavenPackage`, including how to override package attributes with `overrideMavenAttrs` and how to perform offline builds.