Nixpkgs: (ZSH?) JAVA_HOME isn't set correctly when installed to the system profile

Created on 3 Mar 2016  路  13Comments  路  Source: NixOS/nixpkgs

Basic info

To make sure that we are on the same page:

  • Kernel: Linux madoka.brage.info 4.4.2 #1-NixOS SMP Wed Feb 17 20:31:25 UTC 2016 x86_64 GNU/Linux
  • System: 16.03pre77568.40c586b (Emu)
  • Nix version: nix-env (Nix) 1.11.2
  • Nixpkgs version: "16.03pre77568.40c586b"

Describe your issue here

environment.systemPackages includes openjdk. However, the JAVA_HOME environment variable is not set. While this isn't a problem for scripts run through nix-shell -i bash, it breaks scripts that aren't. Possibly part of the reason for this is my use of ZSH as a default shell.

Expected result

JAVA_HOME should be set.

Actual result

It is not set.

Steps to reproduce

echo $JAVA_HOME.

Notice that it isn't set.

Most helpful comment

On NixOS

programs.java.enable = true;

now sets up JAVA_HOME system-wide.

All 13 comments

This is quite likely to be an ZSH issue. The exact same (simple) script fails if I use -i zsh, whereas it works with -i bash.

Nope. Not an ZSH issue. I'm not sure why I got the behaviour above earlier, but now I can't reproduce it.

Ha! I've got jdk on my systemPackages, but my $JAVA_HOME is not set, neither in zsh nor in bash.
With nix-shell -p jdk, it is set. I didn't even know about that hook. How is it not present for systemPackages?

@bendlas Good question! :)

I've got a temporary fix in the PR referenced above, but if you're comfortable enough with applying that locally then you can probably just use nix-shell until it's fixed properly. Whatever "properly" turns out to mean.

Just to clarify, when you use nix-shell -p the packages gets added to your shell dependencies and their respective setup-hooks are introduced into the environment. When they are aggregated into a profile they are not dependencies of your shell. I'm not convinced that it is a good idea to introduce the setup-hook when added to a profile but I also don't think that your issue is unreasonable.

I'll take that up on the mailing list.

The issue is, though, that if JAVA_HOME isn't set then a lot of Java applications just won't work... And every other distribution does set the variable by default, so we should too.

I'm not sure how to deal with upgrades. Possibly it'll need another symlink in /run. Anyway, mailing list...

JAVA_HOME should not be set globally. There should be some java wrapper which sets it to whatever value of JAVA_HOME is desirable for that application.

As a concrete test case: env | grep -q JAVA_HOME should return an exit status of 1 regardless of how it is installed in any shell like zsh or bash.

Would like to know if there is a well documented workaround for this somewhere, trying to install sbt-ensime and it complains with this error, not sure if this is something that can be fixed the "nix way"... correct me if I'm wrong please.

I am not convinced that nix shouldn't handle environment variables for user profiles, but maybe I could be convinced. A common situation, not unrelated to the current issue, is that apparently nix-shell has some downsides for graphical applications (not speaking from personal experience, but citing someone who seems to know more about nix than me):

And another nitpick. You'll soon find very incovenient to launch IDE from shell every time. It seems a good idea to specify, that some package is used for development, but nix-shell doesn't work well for non-cli applications. Not to mention occasional problems with Nix GC and nix-shell. You'd better install IDE globally or per-user, it is better long-term solution.

nix-env already defines our environment by defining what is effectively in our PATH, so why not allow it to define other parts of our environment, rather than having to devise our own solutions on a case-by-case basis? I'm not saying it will work for everything, but I would think it could easily work for common cases such as this.

@roman My solution for now, which may be an OK way to do this:

I have the following script, nix-env-dynamic.sh:

#!/bin/bash

export JAVA_HOME=$(readlink -e $(type -p javac) | sed  -e 's/\/bin\/javac//g')
export IDEA_JDK=/usr/lib/jvm/zulu-8-amd64
ln -sfT $JAVA_HOME $ENVSDIR/JDK

A couple of extra lines there to make intellij happy - first to give it its own JVM that works well with it, and second, to provide a linked path I can easily fine for the current nix JDK, since IntelliJ doesn't like to use the environment's JAVA_HOME to find JDKs.

I have a docker container running nix/nixpkgs that has its entrypoint do some configuration to .bashrc; the related part for this is shown next, but I assume most aren't using docker, so just add it to your .bashrc normally in that case (e.g. source $HOME/workspace/nix-env-dynamic.sh)

SET_DYNAMIC_ENV="source $HOME/workspace/nix-env-dynamic.sh"
grep -q -F "${SET_DYNAMIC_ENV}" $HOME/.bashrc || printf "\n$SET_DYNAMIC_ENV\n" >> $HOME/.bashrc

That said, I'd like to do as little bash/perl programming as possible - I suspect you can relate ;). So, I still think it might be nice for Nix to handle this at some level.

@bbarker this saves you the sed command and the which dependency:

export JAVA_HOME="${$(readlink -e $(type -p java))%*/bin/java}"

@NeQuissimus I'm so inured to which that I hadn't even thought of it as a dependency, but I can see that it is probably not something used much in Nix - I feel sed is probably more standard. I couldn't quite get your command to work and am not good enough with bash to easily fix, so I went with replacing which with type -p - thanks!:

export JAVA_HOME=$(readlink -e $(type -p javac) | sed  -e 's/\/bin\/javac//g')

On NixOS

programs.java.enable = true;

now sets up JAVA_HOME system-wide.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chris-martin picture chris-martin  路  3Comments

ayyess picture ayyess  路  3Comments

domenkozar picture domenkozar  路  3Comments

langston-barrett picture langston-barrett  路  3Comments

tomberek picture tomberek  路  3Comments