microsoft / vscode-maven

VSCode extension "Maven for Java"
https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-maven
Other
182 stars 88 forks source link

maven.terminal.useJavaHome doesnt work if JAVA_HOME already set by shell startup scripts #495

Open jahan01 opened 4 years ago

jahan01 commented 4 years ago

Describe the bug "maven.terminal.useJavaHome": true, or maven.terminal.customEnv doesnt override JAVA_HOME on zsh. It works in bash shell (by changing"terminal.integrated.shell.osx": "/bin/bash").

Due to this I am not able to compile/package my project by clicking in mvn explorer as by default it uses my system jdk, not my project jdk as specified in java.home

To Reproduce Steps to reproduce the behavior:

  1. Set below settings and make sure your default shell is zsh on mac.
"java.home": "/my/jdk/path",
"maven.terminal.useJavaHome": true,
"maven.terminal.customEnv": [
    {
        "environmentVariable": "JAVA_HOME",
        "value": "/my/jdk/path"
    },
    {
        "environmentVariable": "MY_MVN_ENV",
        "value": "my value"
    }
],
  1. Goto maven in explorer, and try to create a terminal by running mvn goal. For example run a custom goal of -version
  2. Check if Java version: in the console is same as java.home in your settings, not the JAVA_HOME set by your .zshrc or .zshenv
  3. However maven.terminal.customEnv is able to set variables other then JAVA_HOME. i.e, MY_MVN_ENV is set properly in the terminal

Expected behavior System wide JAVA_HOME is overridden with java.home and able to compile using project specific JDK version.

Environments (please complete the following information as much as possible):

Eskibear commented 4 years ago

Here is a misunderstanding of setting maven.terminal.useJavaHome, it's indicating whether you are going to use value of setting java.home as your JAVA_HOME... You can set it to false, and have a try. Let me know if it works or not.

jahan01 commented 4 years ago

Okay, I am not clear how this works. I am listing the info from my system .zshenv

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home

settings.json

"java.home": "/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home",
"maven.terminal.useJavaHome": true,

Run custom maven goal from explorer -version

Java version: 11.0.6.0.1,

Change this settings

"maven.terminal.useJavaHome": false,

I still get JDK 11 when I run -version

Java version: 11.0.6.0.1,

My intention is to use JDK 8, which is specific to this project and not global JDK 11.

Eskibear commented 4 years ago

Sorry about the misleading. If you want to use a specific JAVA_HOME, you can either:

I can reproduce your zsh issue, and it works well for bash as you mentioned. This extension tells vscode to append custom envs(e.g. JAVA_HOME) when opening a new integrated terminal. I just double checked it, the envs are correctly passed to vscode. and I guess that's probably related to how vscode loads the profiles, for zsh particularly.

Let me share my findings.

I have JDK 11/13/14 installed.

.bash_profile

# No JAVA_HOME specified

.zshenv

export JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-13.jdk/Contents/Home

settings.json

"java.home": "/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home",
"maven.terminal.useJavaHome": true,

For Bash

Run mvn -version in a manually created terminal.

Java version: 14.0.1

Run custom maven goal from explorer -version

Java version: 11.0.7

For Zsh

Now I set "terminal.integrated.shell.osx": "/bin/zsh", it's buggy. Run mvn -version in a manually created terminal.

Java version: 13.0.2

Run custom maven goal from explorer -version

Java version: 13.0.2

Now if I remove JAVA_HOME from .zshenv, it's working as expected Run mvn -version in a manually created terminal.

Java version: 14.0.1

Run custom maven goal from explorer -version

Java version: 11.0.7

My guess is, for zsh, vscode first loads the custom envs passed by this extension, and later from .zshenv.

Eskibear commented 4 years ago

@jahan01 try printing out the values in .zshenv like below, which somehow proves my hypothesis above.

echo before:$JAVA_HOME
export JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-13.jdk/Contents/Home
echo after:$JAVA_HOME

I'm not familiar with zshell, but I think there's no way to interfere zshell's behavior in this extension...

jahan01 commented 4 years ago

@Eskibear : yes, you are right in saying that vscode sets the env variable at the terminal creation but it is overridden if the avariables are also set in shell start up scripts(.zshrc, .zshenv or .bash_profile etc.,)

I just observed behaviour is same both in zsh and bash. If you set JAVA_HOME in .bashrc, vscode is not able to override with maven.terminal.useJavaHome or maven.terminal.customEnv or even terminal.integrated.env.osx doesn't work in both the shells.

This also doesnt work (i.e., overridden by shell startup scripts)

 "terminal.integrated.env.osx": {
        "JAVA_HOME": "/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home",
   }

Earlier I had not set JAVA_HOME in .bash_profile so I assumed it was working fine in bash. Turns out this behaviour is same in both bash and zsh.

Eskibear commented 4 years ago

OK, then I think it can be a regression introduced by https://github.com/microsoft/vscode-maven/pull/240 .

Previously it manually executed "export" statements for different kind of shells. So no matter what was written in the startup scripts, the command finally won...

Do you think we should revert the change and back to previous behavior? The side effect would be:

also /cc @jdneo

jahan01 commented 4 years ago

@Eskibear I am not an expert, but this is exactly what vscode-python extension do to activate virtual environment (though it doesnt do export, but I think approach is similar to what you describe). After terminal creation it assembles the command based on OS and virtual env and send them as a text to be executed.

Somehow, intellij idea and pycharm doesnt need to do these hacks, somehow the set correct variables without executing statements after terminal creation.

jahan01 commented 4 years ago

BTW, FYI I have opened a ticket in microsoft/vscode#98490 to get terminal.integrated.env.osx fixed.

jahan01 commented 4 years ago

@Eskibear : I think VSCode has new API now for extensions to contribute to env variable in integrated terminals. See here and here

thakkarparth007 commented 2 years ago

java.home has been deprecated recently. VSCode wants us to use 'java.jdt.ls.java.home' instead. As a result, I was not setting java.home in settings.json, and this extension kept giving JAVA_HOME not set correctly errors. So, I set java.home anyway and the extension stopped facing issues. This is a temporary workaround though, and ideally the extension should now read java.jdt.ls.java.home instead of java.home.

Eskibear commented 2 years ago

@thakkarparth007 Thank you for reporting this. When did you see this error, and what's the full error message?

thakkarparth007 commented 2 years ago

@Eskibear here's the error message I got when I saved a pom.xml file, or on clicking the "Dependencies" option in the maven toolbar.

Spawn {"command":"\"/home/parthdt2/apache-maven-3.8.4/bin/mvn\"","args":["-N","com.github.ferstl:depgraph-maven-plugin:3.3.1:graph","-DgraphFormat=text","-DshowDuplicates","-DshowConflicts","-DshowVersions","-DshowGroupIds","-DoutputDirectory=\"/home/parthdt2/.vscode-server/data/User/workspaceStorage/dea46b679bf34fed54910712a5990448/vscjava.vscode-maven\"","-DoutputFileName=\"044fa7c3c75de7b20913fb184edd5478.deps.txt\"","-f","\"/home/parthdt2/project/java_transformations/java_transformations/pom.xml\""]}
The JAVA_HOME environment variable is not defined correctly,
this environment variable is needed to run this program.

This is when my settings.json file looked like this:

{
    //"java.home": "/home/parthdt2/.jabba/jdk/adopt@1.16.0-1",
    //"java.jdt.ls.java.home": "/home/parthdt2/.jabba/jdk/adopt@1.16.0-1",
    "terminal.integrated.env.linux": {
        "JAVA_HOME": "/home/parthdt2/.jabba/jdk/adopt@1.16.0-1"
    },
    "terminal.integrated.defaultProfile.linux": "zsh",
    "maven.executable.path": "/home/parthdt2/apache-maven-3.8.4/bin/mvn",
    "maven.terminal.useJavaHome": true // tried both commenting and uncommenting this.
}

I'm using Jabba for managing Java environments, and my ~/.zshrc loads the jdk automatically. Therefore, whenever a new terminal is opened, the JAVA_HOME variable is correctly set. However, vscode-maven seems to use spawn, and my VSCode doesn't load ~/.zshrc while starting, so the spawn function never gets to see the JAVA_HOME variable anywhere.

After seeing the explanation for maven.terminal.useJavaHome (Maven › Terminal: Use Java Home If this value is true, and if the setting java.home has a value, then the environment variable JAVA_HOME will be set to the value of java.home when a new terminal window is created.), I tried setting java.jdt.ls.java.home because that's the recommended way to set java.home, but that setting made no difference to vscode-maven. So I then set java.home explicitly ignoring VSCode's complains, and then vscode-maven was happy.

I've tried to give all details I could think of, let me know if you need more details!

Eskibear commented 2 years ago

Thanks, it's very helpful for locating the problem.

The problem is, Maven requires you to set JAVA_HOME env (e.g. to run mvn commands), and you don't have the JAVA_HOME set in your zsh profile.

So I then set java.home explicitly ignoring VSCode's complains, and then vscode-maven was happy.

If java.home can work it around, then you may try maven.terminal.customEnv, see if it works.

thakkarparth007 commented 2 years ago

you don't have the JAVA_HOME set in your zsh profile.

But I do have JAVA_HOME set in my zsh profile. I run jabba use adopt@1.16.0-1 in the zshrc, and that automatically sets JAVA_HOME. I think the problem might be that the spawn call does not load the shell profile before executing the commands.

I'll try maven.terminal.customEnv and let you know.

Eskibear commented 2 years ago

BTW, I just searched vscode's repo for zsh issues, check if https://github.com/microsoft/vscode/issues/143061 helps?

yorkish commented 1 year ago

Trying to make it work on

RockyLinux 8.6 VsCode 1.73.1 Maven extension 0.39.2

I`ve added this piece of config everywhere (User / Workspace / Folder )

    "maven.terminal.customEnv": [
        {
            "environmentVariable": "FOO",
            "value": "bar"
        }
    ]

And opening a new integrated shell only to find that the FOO env variable isn't present.

tried that after banging my head over JAVA_HOME.

so the problem isn't linked to having JAVA_HOME set in .bashrc

ivorobioff commented 1 year ago

I wrote a simple maven plugin to test this problem out, and here's what I found. So, I use WSL2 with Ubuntu 22.04. JAVA_HOME is set to /home/linuxbrew/.linuxbrew/opt/openjdk@11. So, if I don't specify JAVA_HOME in maven.terminal.customEnv then within my plugin JAVA_HOME == null which makes sense. However, if I do specify JAVA_HOME but with different path not the one is set by default in the system then within my plugin I get the path assigned by default in the system not in the maven.terminal.customEnv configuration. It's definitely not working okay. You can see the screenshots demonstrating it.

Here I set JAVA_HOME to use a different sdk not the one specified in the system:

foo

Here, I don't specify JAVA_HOME at all:

bar

Eskibear commented 1 year ago

Looks like JAVA_HOME is not loaded when vscode starts the terminal. Can you run echo $JAVA_HOME in the terminal where JAVA_HOME is null?

Kambaa commented 1 year ago

Update: How about this approach? https://www.baeldung.com/maven-different-jdk#setting-up-javahome-only-for-maven

https://stackoverflow.com/a/43524685/1020512

Hello, after this happenned to me, i read this page and done some googling. According to the links that i'll write below, we need JAVA_HOME env variable set to use maven commands successfully. So before anything, if we want to do some 'specific' JDK usage on maven, i think we need to set the JAVA_HOME explicitly, and then run the appropriate maven command.

https://www.baeldung.com/maven-java-home-jdk-jre https://stackoverflow.com/questions/15279586/java-home-in-maven https://subscription.packtpub.com/book/application-development/9781785286124/1/ch01lvl1sec13/changing-the-jdk-used-by-maven (NOT So much for our case but good to know the options) https://maven.apache.org/plugins/maven-compiler-plugin/examples/compile-using-different-jdk.html https://stackoverflow.com/questions/2503658/specify-jdk-for-maven-to-use (check maven.terminal.useJavaHome did not work for me on /individual project folder and workspace level) https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-maven

cypher256 commented 9 months ago

On macOS, the following solved the problem. The following JAVA_HOME takes precedence over the OS JAVA_HOME environment variable.

"maven.terminal.customEnv": [
    {
        "environmentVariable": "JAVA_HOME",
        "value": "/xxx/java/21"
    },
    {
        "environmentVariable": "ZDOTDIR",
        "value": "~/.zsh_dummy"
    },
],
cypher256 commented 9 months ago

Related Issue: #991 Change the scope of maven.terminal.customEnv to machine-overridable

cypher256 commented 9 months ago

Another ways to ignore the system's JAVA_HOME env var.

macOS

settings.json

"maven.terminal.customEnv": [
    {
        "environmentVariable": "JAVA_HOME",
        "value": "/xxx/java/21"
    },
    {
        "environmentVariable": "ZDOTDIR",
        "value": "/xxx/rcdir"
    }
],

/xxx/rcdir/.zshrc (See repository)

if [ -r ~/.zshrc ]; then
    JAVA_HOME_BACKUP=$JAVA_HOME
    source ~/.zshrc
    export JAVA_HOME=$JAVA_HOME_BACKUP
fi
export PATH="$JAVA_HOME/bin:$PATH"

Linux

settings.json

"maven.terminal.customEnv": [
    {
        "environmentVariable": "JAVA_HOME",
        "value": "/xxx/java/21" // For Maven
    }
],
"terminal.integrated.profiles.linux": {
    "bash": {
        "path": "bash",
        "env": {"JAVA_HOME": "/xxx/java/17"}, // Terminal Default
        "args": ["--rcfile", "/xxx/rcdir/.bashrc"]
    },
},

/xxx/rcdir/.bashrc (See repository)

if [ -r ~/.bashrc ]; then
    JAVA_HOME_BACKUP=$JAVA_HOME
    source ~/.bashrc
    export JAVA_HOME=$JAVA_HOME_BACKUP
fi
export PATH="$JAVA_HOME/bin:$PATH"

Windows

settings.json

"maven.terminal.customEnv": [
    {
        "environmentVariable": "JAVA_HOME",
        "value": "C:¥¥xxx¥¥java¥¥21"
    }
],
Guan-Meng-Yuan commented 3 days ago

hi,this is my .zshrc. It is working normally now.


if [ -z "$JAVA_HOME" ]; then
    JAVA_HOME=$(/usr/libexec/java_home)
    export JAVA_HOME
    echo "JAVA_HOME not set, defaulting to $JAVA_HOME"
else
    echo "JAVA_HOME is already set to $JAVA_HOME"
fi