Run a program from maven using jbang

I’d like to use quarkus and I wanted to follow this Get Started - Quarkus. As I understand, to install quarkus, I need to use jbang that will pick the CLI program in Maven’s repository. However, if I do:

$ nix-shell -p jbang
$ jbang app install --fresh --force quarkus@quarkusio
[jbang] Command installed: quarkus
[...]
$ quarkus --version
quarkus: command not found

How could I solve this problem?

–EDIT–
Seems like doing $ export PATH=~/.jbang/bin/:$PATH solves the problem. Couldn’t we configure nix-shell to do that automatically?

–EDIT2–
Can I somehow specify in a nix-shell “install jbang and from jbang install quarkus”? For now I’m doing this:

{pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
  packages = with pkgs; [ jbang ];
  shellHook = ''
    echo ">>>> Making sure quarkus is installed"
    jbang app install --fresh --force quarkus@quarkusio
    echo ">>>> Updating PATH"
    export PATH=~/.jbang/bin/:$PATH
    echo ">>>> You can start the debug mode via 'quarkus dev' (this project was created via 'quarkus create')."
  '';
}

but it does not seem to be really optimized (and there is no guarantee that the quarkus version will match between multiple users I guess)

If you use JBang, it will install whatever version it decides to. You can just get quarkus directly from Github
Releases · quarkusio/quarkus · GitHub
That way you can build a normal Nix package.

Thanks. So basically, JBang is the quick and dirty, and packaging is the clean and long approach. So I tried to write this:

# This method is the simplest, but not the cleanest (download the whole maven dependency in one output)
# https://nixos.org/manual/nixpkgs/stable/#maven
{ stdenv, maven, lib, fetchFromGitHub }:
stdenv.mkDerivation rec {
  name = "quarkus-${version}";
  version = "2.10.1.Final";

  src = fetchFromGitHub {
    owner = "quarkusio";
    repo = "quarkus";
    rev = "${version}";
    sha256 = "sha256-OUxVkKFqAEwWQiwvVJfetHC0nEPARvYXpeu8bKSVu7M=";
  };

  buildInputs = [ maven ];

  buildPhase = ''
    mvn package -Dmaven.repo.local=$out -Dmaven.test.skip=true
  '';
  
  # keep only *.{pom,jar,sha1,nbm} and delete all ephemeral files with lastModified timestamps inside
  installPhase = ''
    find $out -type f \
      -name \*.lastUpdated -or \
      -name resolver-status.properties -or \
      -name _remote.repositories \
      -delete
  '';

  # don't do any fixup
  dontFixup = true;
  outputHashAlgo = "sha256";
  outputHashMode = "recursive";
  # replace this with the correct SHA256
  outputHash = lib.fakeSha256;

  meta = {
    description = "";
    homepage = https://github.com/quarkusio/quarkus;

    # license = stdenv.lib.licenses.;
    # maintainers = [ stdenv.lib.maintainers. ];
    # platforms = stdenv.lib.platforms.;
  };
}

unfortunately a test appears to fail (gRPC - Stubs for health and reflection ), but I can’t find how to disable tests (sorry, I’m very new to the Java ecosystem). Using -Dmaven.test.skip=true does not solve the problem.

See this question where I give the precise error Can't package Quarkus

Building Java programs with Nix is a nightmare. I got the compiled jar to work with this self-contained example:

quarkus-cli.nix

{ pkgs ? <nixpkgs>
}:
let
  quarkus-cli = { stdenv, fetchurl, writeScript, bash, openjdk }: 
    stdenv.mkDerivation rec {
      pname = "quarkus-cli";
      version = "2.10.1.Final";

      src = fetchurl {
        url = "https://github.com/quarkusio/quarkus/releases/download/2.10.1.Final/${pname}-${version}.tar.gz";
        sha256 = "0cl641g5vgw94ac7sj8mhz21s6rkjdfjdzhh02dq64cd5cxwcmc5";
      };

      launcher = writeScript pname ''
        #! ${bash}/bin/bash

        export CLASSPATH=@LIB@/${pname}-${version}-runner.jar

        exec ${openjdk}/bin/java $JAVA_OPTS -classpath $CLASSPATH -Dapp.name="quarkus" -Dapp-pid="$$" -Dapp.repo="@LIB@" -Dapp.home="@OUT@" -Dbasedir="@OUT@" io.quarkus.cli.Main "$@"
      '';

      installPhase = '' 
        mkdir -p $out/{lib,bin}

        cp ./lib/${pname}-${version}-runner.jar $out/lib
        cp ${launcher} $out/bin/${pname}
        substituteInPlace $out/bin/${pname} --replace @LIB@ $out/lib --replace @OUT@ $out
      ''; 
   };
in
  (import pkgs {}).callPackage quarkus-cli {}
2 Likes

Thanks a lot!! (your trick with @OUT@ is also funny) Too bad compiling is not easy (I’ll read now the other conversation for that) But your solution is actually more interesting from a practical point of view as it does not compile anything and is therefore close to instantaneous. Note however that to make it work, you need to have export JAVA_HOME="${openjdk}" before the exec, otherwise the application won’t compile when running it with quarkus-cli dev.