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