Help packaging a Java app?

I’d like to package Rachota, a timetracking app. I see that it’s designed to be built with Maven, but I don’t know the first thing about that tool (or Java development in general). I also see that there are no Nixpkgs docs about using maven, and that there are a two(?) functions for building maven projects in nixpkgs code base. One of them requires a secondary tool, mvn2nix. It is not immediately clear to me how to use any of these tools, and there aren’t any examples to crib off of in the nixpkgs repo.

Could someone point me to examples of Maven-built packages that would be good to copy from? Or give me pointers of any sort? :slight_smile:

Thanks!

3 Likes

If the app has little number of dependencies to download, you can model your code after processing (https://github.com/NixOS/nixpkgs/blob/9541c6b7bf0c2ce78633fd27498121ef28975881/pkgs/applications/graphics/processing/default.nix) (it uses ant but there is no big difference, just replace ant build with mvn package)

If there is a lot of jars to download from maven cental, then it is a problem which has many solutions. none of them is perfect.

  1. Maven can be run twice, the first time to download all dependencies into fixed-output derivation and the second for the offline build (example https://github.com/NixOS/nixpkgs/blob/44aca430c3745c8a5de75afc7b170f5dc0e21bd0/pkgs/applications/science/misc/gephi/default.nix). Disadvantage: outputHash of the FOD is drifting with time and will need to be updated in few months (because maven dependencies can refer to “latest” vesrion of some artifact, and when the artifact is updated, the output of the phase is changed)
  2. Make a big list of all dependencies (example https://github.com/NixOS/nixpkgs/blob/d80de1b135cf098d8acd134385400fe3956a59e5/pkgs/development/compilers/graalvm/default.nix#L64-L69). Disadvantage: difficult to maintain and update. This is where tools like mvn2nix are suppose to help.
  3. Mixes of the two approaches above (example: https://github.com/NixOS/nixpkgs/tree/92a047a6c4d46a222e9c323ea85882d0a7a13af8/pkgs/applications/networking/cluster/chronos)
3 Likes

As I wrote in Shell.nix or default.nix for java project I have used Mavenix for some projects at work and was quite happy with the experience. Mavenix creates a lock file and a Nix expression. The latter can be modified, however, one needs to be careful because it may break the script that is used to update the lock file. There were some issues but together with the maintainer of Mavenix those were resolved quite quickly. Unfortunately I do not have any public projects to share.

5 Likes

This github issue documents the problem somewhat, and discusses some alternatives:

Thanks for the tips, folks! I’ll let you know how it goes.

@chreekat I documented the solution @volth proposed to “run maven twice” https://fzakaria.com/2020/07/20/packaging-a-maven-application-with-nix.html

I went through the process for an application of mine recently. I tried to write it to explain step-by-step what is happening; hope it helps.

I’m also seeking contributors to mvn2nix a separate utility to generate Nix attrset for the dependency closure of a Maven applicatin.

@fzakaria
Thanks!
That would need immutable snapshots of whole Maven central to work properly (to have stable sha256s)

What would need a whole snapshot of maven central ?

The dependency closure of an application is stable if it doesn’t use SNAPSHOT type dependencies.

POM files might refer to version ranges instead of exact versions.
For example hadoop depends on jodatime "at least 2.9", and with every new jodatime release Maven (the 1st pass) picks the latest version, producing different output with different sha256

@fzakaria you should publish mvn2nix on our community at https://weekly.nixos.org/ (https://github.com/NixOS/nixos-weekly/pulls), perhaps as an alternative to https://github.com/NixOS/mvn2nix-maven-plugin .

@volth although pom files technically could specify a version range:
1 - it’s quite uncommon
2 - the solution I proposes first builds an “effective-pom.xml” which is a pom file with all the dependencies pinned down. The solution uses the same dependency traversing algorithm as Maven (by using Maven’s internal libraries) to figure out the actual closure that will be resolved.

@doronbehar I will send a PR with some content I have created for the nixos-weekly

@volth your comment about snapshot of whole Maven central had me thinking about “multiple output derivations”

I had a crazy idea to create a single derivatoin for “mvncentral” which is a multiple output derivation for each individual JAR One could specify the output of a subfolder for the organizations you wanted to pull in.

hadoop 3.3.0 (in https://github.com/NixOS/nixpkgs/pull/68817) has two more issues, but “run maven twice” solves them too :slight_smile:

  1. there are executables downloaded from Maven Central, which need to be patchelfed to run on NixOS
  2. besides Maven Central, there are downloads of NodeJS packages from NPM

Ah yes.
You can hijack maven to distribute machine binaries!
:slight_smile:

I’ve quickly learnt writing mvn2nix how wide scoped the tool is.

2 Likes