Home Explore Blog CI



nixpkgs

5th chunk of `doc/languages-frameworks/maven.section.md`
c46e270207fb787babc0643fa843d8a6cf3ea73a581f824d0000000100000fce
  outputHash = lib.fakeHash;
}
```

The build will fail, and tell you the expected `outputHash` to place. When you've set the hash, the build will return with a `/nix/store` entry whose contents are the full Maven repository.

::: {.warning}
Some additional files are deleted that would cause the output hash to change potentially on subsequent runs.
:::

```bash
❯ tree $(nix-build --no-out-link double-invocation-repository.nix) | head
/nix/store/8kicxzp98j68xyi9gl6jda67hp3c54fq-maven-repository
├── backport-util-concurrent
│   └── backport-util-concurrent
│       └── 3.1
│           ├── backport-util-concurrent-3.1.pom
│           └── backport-util-concurrent-3.1.pom.sha1
├── classworlds
│   └── classworlds
│       ├── 1.1
│       │   ├── classworlds-1.1.jar
```

If your package uses _SNAPSHOT_ dependencies or _version ranges_; there is a strong likelihood that over-time your output hash will change since the resolved dependencies may change. Hence this method is less recommended then using `buildMaven`.

### Building a JAR {#building-a-jar}

Regardless of which strategy is chosen above, the step to build the derivation is the same.

```nix
{
  stdenv,
  maven,
  callPackage,
}:
let
  # pick a repository derivation, here we will use buildMaven
  repository = callPackage ./build-maven-repository.nix { };
in
stdenv.mkDerivation (finalAttrs: {
  pname = "maven-demo";
  version = "1.0";

  src = builtins.fetchTarball "https://github.com/fzakaria/nixos-maven-example/archive/main.tar.gz";
  buildInputs = [ maven ];

  buildPhase = ''
    runHook preBuild

    echo "Using repository ${repository}"
    mvn --offline -Dmaven.repo.local=${repository} package;

    runHook postBuild
  '';

  installPhase = ''
    runHook preInstall

    install -Dm644 target/${finalAttrs.pname}-${finalAttrs.version}.jar $out/share/java

    runHook postInstall
  '';
})
```

::: {.tip}
We place the library in `$out/share/java` since JDK package has a _stdenv setup hook_ that adds any JARs in the `share/java` directories of the build inputs to the CLASSPATH environment.
:::

```bash
❯ tree $(nix-build --no-out-link build-jar.nix)
/nix/store/7jw3xdfagkc2vw8wrsdv68qpsnrxgvky-maven-demo-1.0
└── share
    └── java
        └── maven-demo-1.0.jar

2 directories, 1 file
```

### Runnable JAR {#runnable-jar}

The previous example builds a `jar` file but that's not a file one can run.

You need to use it with `java -jar $out/share/java/output.jar` and make sure to provide the required dependencies on the classpath.

The following explains how to use `makeWrapper` in order to make the derivation produce an executable that will run the JAR file you created.

We will use the same repository we built above (either _double invocation_ or _buildMaven_) to setup a CLASSPATH for our JAR.

The following two methods are more suited to Nix then building an [UberJar](https://imagej.net/Uber-JAR) which may be the more traditional approach.

#### CLASSPATH {#classpath}

This method is ideal if you are providing a derivation for _nixpkgs_ and don't want to patch the project's `pom.xml`.

We will read the Maven repository and flatten it to a single list. This list will then be concatenated with the _CLASSPATH_ separator to create the full classpath.

We make sure to provide this classpath to the `makeWrapper`.

```nix
{
  stdenv,
  maven,
  callPackage,
  makeWrapper,
  jre,
}:
let
  repository = callPackage ./build-maven-repository.nix { };
in
stdenv.mkDerivation (finalAttrs: {
  pname = "maven-demo";
  version = "1.0";

  src = builtins.fetchTarball "https://github.com/fzakaria/nixos-maven-example/archive/main.tar.gz";
  nativeBuildInputs = [ makeWrapper ];
  buildInputs = [ maven ];

  buildPhase = ''
    runHook preBuild

    echo "Using repository ${repository}"
    mvn --offline -Dmaven.repo.local=${repository} package;

    runHook postBuild
  '';

  installPhase = ''
    runHook preInstall

    mkdir -p $out/bin

Title: Building JARs and Runnable JARs with Maven and Nix
Summary
This section details how to build JAR files and runnable JARs using Maven and Nix. It first discusses setting the `outputHash` in the double invocation method. Then it explains how to build a regular JAR file by specifying the repository and using Maven to package the project. Finally, it covers creating a runnable JAR using `makeWrapper` and setting up a CLASSPATH to include the necessary dependencies from the Maven repository. The passage recommends using a CLASSPATH approach rather than building an UberJar for better integration with Nix.