Mvn2nix: packaging maven application made easy

I wanted to share the initial release of mvn2nix; which is a new nixpkgs tooling to help package Maven applications as Nix derivations.

Easily package your Maven Java application with the Nix package manager.

mvn2nix comes with 2 building blocks, the self-titled utility and the buildMavenRepsitory Nix expression.

Basic Premise

First a dependencies.nix file is generated by running mvn2nix over your Maven project.

$ nix run -f https://github.com/fzakaria/mvn2nix/archive/master.tar.gz \
        --command mvn2nix > dependencies.nix

$ head dependencies.nix
{
  "junit:junit:pom:3.8.1" = {
    url = "https://repo.maven.apache.org/maven2/junit/junit/3.8.1/junit-3.8.1.pom";
    layout = "junit/junit/3.8.1/junit-3.8.1.pom";
    sha256 = "e68f33343d832398f3c8aa78afcd808d56b7c1020de4d3ad8ce47909095ee904";
  };
  "org.sonatype.forge:forge-parent:pom:10" = {
    url = "https://repo.maven.apache.org/maven2/org/sonatype/forge/forge-parent/10/forge-parent-10.pom";
    layout = "org/sonatype/forge/forge-parent/10/forge-parent-10.pom";
    sha256 = "c14fb9c32b59cc03251f609416db7c0cff01f811edcccb4f6a865d6e7046bd0b";

This dependencies.nix file can then be fed into buildMavenRepsitory to generate a linkFarm in the form of a maven repository.

let mvn2nix = import (fetchTarball https://github.com/fzakaria/mvn2nix/archive/master.tar.gz) { };
in
mvn2nix.buildMavenRepsitory { dependencies = import ./dependencies.nix; }

This creates a /nix/store path which is a Maven repository that can be used, such as in mvn package --offline -Dmaven.repo.local=${mavenRepository}

$ tree /nix/store/2ps43297g5nii2k15kfy8z46fam51d8x-buildMavenRepository | head

/nix/store/2ps43297g5nii2k15kfy8z46fam51d8x-buildMavenRepository
β”œβ”€β”€ com
β”‚   └── google
β”‚       β”œβ”€β”€ code
β”‚       β”‚   └── findbugs
β”‚       β”‚       └── jsr305
β”‚       β”‚           └── 3.0.2
β”‚       β”‚               └── jsr305-3.0.2.jar -> /nix/store/w20lb1dk730v77qis8l6sjqpljwkyql7-jsr305-3.0.2.jar
β”‚       β”œβ”€β”€ errorprone
β”‚       β”‚   └── error_prone_annotations

There’s nothing specific here for Maven and the approach here should be easily applicable to Gradle packages as well.

Looking forward to feedback, and you can also find me now on the new #java channel on the NixOS Discord server.

logo_128x128
built with nix

Thanks to @roberth & @DerGuteMoritz for your help.

12 Likes

Nice! We need more java stuff if we want to better make inroads in certain enterprises.

2 Likes

It’s really neat to see the transitive closure of your Java application now, since all the third party JARs
are a runtime dependency within the buildMavenRepository derivation.

/nix/store/lld88yvvaz6895x27517y7v6xfq0dhnx-mvn2nix-0.1
+---/nix/store/j8vysakw78bpgngba32hfwwikqda9yx2-bash-4.4-p23
|   +---/nix/store/aqq6367snc1zh3fs1pc4j4zm5h80vkkz-glibc-2.31
|   |   +---/nix/store/fwrhy0xaxzm2fp3fh29939n529vi7dxz-libidn2-2.3.0
|   |   |   +---/nix/store/dp7i2xjbmmgn5r69jh7iiw57z54nnn6h-libunistring-0.9.10
|   |   |   |   +---/nix/store/dp7i2xjbmmgn5r69jh7iiw57z54nnn6h-libunistring-0.9.10 [...]
|   |   |   +---/nix/store/fwrhy0xaxzm2fp3fh29939n529vi7dxz-libidn2-2.3.0 [...]
|   |   +---/nix/store/aqq6367snc1zh3fs1pc4j4zm5h80vkkz-glibc-2.31 [...]
|   +---/nix/store/j8vysakw78bpgngba32hfwwikqda9yx2-bash-4.4-p23 [...]
+---/nix/store/qkkif6z2wsn4gqqjsgk9s475lq3s1dhc-openjdk-headless-11.0.8+10
|   +---/nix/store/aqq6367snc1zh3fs1pc4j4zm5h80vkkz-glibc-2.31 [...]
|   +---/nix/store/41ps3rrqcs5xfpm3ckpvjrjbnrzi0w8x-zlib-1.2.11
|   |   +---/nix/store/aqq6367snc1zh3fs1pc4j4zm5h80vkkz-glibc-2.31 [...]
|   +---/nix/store/8d23f6mrlr987qnyaaga6qv4wkwy3x1k-lcms2-2.11
|   |   +---/nix/store/aqq6367snc1zh3fs1pc4j4zm5h80vkkz-glibc-2.31 [...]
|   |   +---/nix/store/8d23f6mrlr987qnyaaga6qv4wkwy3x1k-lcms2-2.11 [...]
|   +---/nix/store/h33yiliyiyaiyi1vkqv29ky00q5pk7lg-hook
|   +---/nix/store/s0i7mmnzapfyr24fxlv1n59f3f0lnqbx-gcc-9.3.0-lib
|   |   +---/nix/store/aqq6367snc1zh3fs1pc4j4zm5h80vkkz-glibc-2.31 [...]
|   |   +---/nix/store/s0i7mmnzapfyr24fxlv1n59f3f0lnqbx-gcc-9.3.0-lib [...]
|   +---/nix/store/s3cf00gm9fkiss8w4z046y1dk6ymjdpp-libjpeg-turbo-2.0.4
|   |   +---/nix/store/aqq6367snc1zh3fs1pc4j4zm5h80vkkz-glibc-2.31 [...]
|   +---/nix/store/qkkif6z2wsn4gqqjsgk9s475lq3s1dhc-openjdk-headless-11.0.8+10 [...]
+---/nix/store/yx0j6yqi0100qslmg5f536jbcsnp1064-buildMavenRepository
|   +---/nix/store/017nv84ai9fzvz1yr6j05dq6ax0bhp78-doxia-sink-api-1.0-alpha-7.pom
|   +---/nix/store/05gvlsvcsf8r383mn4bvplgl9dhdxnpj-surefire-api-2.12.4.jar
|   +---/nix/store/06l0jm065y1cm7163b8ql96bzdirrv1g-aether-impl-1.7.jar
|   +---/nix/store/06mx5qzdwk6ljim18axnyij3xhmkivrr-snappy-0.4.pom
|   +---/nix/store/0744qlqhvyygfln730g0nahxvj2b7d4y-failureaccess-1.0.1.pom
|   +---/nix/store/09rayzn74pi5qpynnc6b59v2mqfdnvgr-maven-plugin-descriptor-2.0.6.pom
|   +---/nix/store/0cnbwbv64jn9vhgjd6xpmm0x50yhvslw-classworlds-1.1.pom
|   +---/nix/store/0hz308yvfr7q6xcqxfg5972jzw2z5j2d-slf4j-jdk14-1.5.6.pom
|   +---/nix/store/0mqhynpn2r5ccr1dxvbc6ai99660kh7h-plexus-containers-1.0.3.pom
|   +---/nix/store/0vb8cf3cqzy81m1f58cfiwmzzp3smxmg-plexus-components-1.1.14.pom
|   +---/nix/store/0wdwgxiryhrsqsl2vn35igdaajwy0vy4-maven-compat-3.0.pom
|   +---/nix/store/0y98vxzs0g0aiygkd0snff7szrzb23wf-maven-project-2.2.1.pom
1 Like

How does Mvn2nix compare to mavenix?

1 Like

@ttuegel having looked mavenix here were my thoughts
(some can be solved with contributions but others more philosophical)

  1. Documentation leaves some to be desired. Doesn’t describe much being β€œrun this”.
  2. Written mostly in bash; would be nice for it to be written in Java + Maven & self-bootstrapped with it’s own tool. (philosophical)
  3. No tests
  4. No support for classifiers for artifacts
  5. mvn2nix downloads artifacts from ~/.m2/repository if it exists to cut down on bandwidth

There are some things I do like about mavenix; which maybe I’ll take inspiration from.

  1. generating a default.nix so that additional inputs can be specified. This is needed if any of the third party dependencies rely on native code or ProcessBuilder
  2. Calculating the effective-pom to figure out the repositories used. Could also probably read the default settings/xml
  3. Format of the lock file is better
3 Likes

How about Haven https://github.com/obsidiansystems/haven ?
Seems like it only supports generating a lock file and not the actual build.

Unfortunately that’s only the dependencies as in compile/runtime/test; but there is a whole slew of build time dependencies like plugins (which have their own transitive dependencies!) that are not shown in dependency:tree :frowning: