Sdkman-cli: It should be possible to use system artifact instead of sdkman's

Created on 16 Oct 2018  ·  32Comments  ·  Source: sdkman/sdkman-cli

Please tick one:

Please explain the Issue / Feature Request here:

It's currently impossible, after using sdkman, to restore Java to use default installed in operation system. It should be possible to do that, even temporarly.

It's done this way by multiple tool version managers like:

  • RVM (https://rvm.io/rvm/basics)
  • NVM (https://github.com/creationix/nvm#system-version-of-node)
  • pyenv (https://github.com/pyenv/pyenv/blob/master/COMMANDS.md#pyenv-global)

I think sdkman could simply remove current binding for a tool with special command, removing current symlink for example:

sdk use java system

or

sdk unuse java

Most helpful comment

I've got to say that I _really_ like the idea of introducing the new unuse command here. I'd expect it to work as an opposing force to the use command ie. _it only affect the current shell_.

In addition I would introduce another new command as counterpart to the default command, and call that system. ie. _affects all subsequent shells that are opened_.

So, this is what you would have:

$ sdk system java     # use system java in all shells
$ sdk default java    # use sdkman java in all shells

$ sdk unuse java      # use the system java only in this current shell
$ sdk use java        # use sdkman java in the current shell

Does this sound like an acceptable approach to everyone?

All 32 comments

I've got to say that I _really_ like the idea of introducing the new unuse command here. I'd expect it to work as an opposing force to the use command ie. _it only affect the current shell_.

In addition I would introduce another new command as counterpart to the default command, and call that system. ie. _affects all subsequent shells that are opened_.

So, this is what you would have:

$ sdk system java     # use system java in all shells
$ sdk default java    # use sdkman java in all shells

$ sdk unuse java      # use the system java only in this current shell
$ sdk use java        # use sdkman java in the current shell

Does this sound like an acceptable approach to everyone?

I must admit I rather like the other approach:

$ sdk use java 8-zulu   # use sdkman java 8 in shell
$ sdk use java system   # use os java in shell

$ sdk default java 11-zulu # use sdkman java 8 in all future shells
$ sdk default java system  # use system java in all future shells

I think I just more used to that approach in other tools like rvm or pyenv. It's also more in line with other commands of sdkman. I think it will be easier to remember for users.

But adding two new commands is just fine as well.

It's basically the choosing between:

  • adding 2 new commands: unused and system
  • adding virtual version system

+0 for virtual version.

@vmj did you mean +1? 😀

@marc0der 😄 no, I meant "I don't feel strongly, but if this happens, the virtual version seemed more natural".

But now that I think about it more, what would the "system" version be for candidates that do not have any system counterpart or have multiple? It's probably "whatever the system was set up it to be". I.e. sdkman will just step aside and let things be as messy as they were before it.

In that case, I feel that unuse/system commands might be a bit easier to understand:

  • sdk unuse java reverts to the default sdkman behaviour for the current shell. That behaviour could be to use one of sdkman java versions or it could be "let the system decide". sdk use java system could do the same, but the words kind of give a promise that there is a single system java.
  • sdk system java undoes the sdkman setup for that candidate and lets the system do whatever it did without sdkman. sdk default java system again kind of gives the impression that sdkman will still be involved when you type java.

So yes, I'm changing my vote to "+0 for new commands". Sorry 😜

But maybe the name of the system command should be something like hide or disable. system is not a verb and sdk system java sounds like a script around /path/to/system/java --version.

@vmj no worries! thanks for clarifying. And yes, good point about system not being a verb.

If you are going for new methods maybe better names will be:

use - unuse
default - undefault

As you see, default is also not a verb.

Maybe change to set-default and unset-default.

@cardil we are using default as a verb in this context. ie we _default_ java to 11.0.1. We also won't be changing that any time soon as it is already widely used by all. I like the idea of introducing undefault as counterpart to default though.

But now that I think about it more, what would the "system" version be for candidates that do not have any system counterpart or have multiple?

Why not simply check if it exists and if there is no system-wide available installation then ask user’s confirmation if that is surely what is wanted?

For multiple choices, sdk can use the system’s alternatives/default resolution tool to show current OS default version like update-alternatives does in Ubuntu for an example.

_Hm… maybe sdk can use system alternatives/default configuration tools to show system version in listing as well while using new version marking like “s” (lowercase) for system-wide available and “S” (uppercase) for currently set system wide default version in addition to “+” and “*”?_

For multiple choices, sdk can use the system’s alternatives/default resolution tool to show current OS default version like update-alternatives does in Ubuntu for an example.

Introducing a dependency on tools that are available only on certain platforms is not good because we would need to start maintaining code branches for every platform under the sun. At the moment sdkman is decoupled as much as possible from it's environment and I think we should keep it that way. Therefore I'm not in favour of depending on tools like update-alternatives on Ubuntu or /usr/libexec/java_home on mac.

Why not simply check if it exists

It's not that simple. We don't know what we are checking for as sdkman is completely agnostic of the contents of the sdks that it serves. ie. we don't know (and don't want to care) what's in the bin folder of each candidate, so we are not even aware that java, scala, groovy, kotlin executables are provided by sdkman.

Uprate-alternatives requires root access. Sdkman is user space program, it shouldn't rely on update-alternatives.

System option is pretty good option even you got nothing installed on system. You are using system, but there nothing there so it effectively unset a tool and disable it's usage.

Came across the need to do this today...

I have Oracle JDK 7 & 8 installed on mac using the installer(s) and OpenJDK 10 & 11 using sdkman.

Switching back to either of the "system" versions after switching to sdk managed version requires mucking about with the PATH

+1 for unuse

@martin-walsh That is absolutely not necessary. Simply use sdkman's local version feature:
https://sdkman.io/usage#localversion

@marc0der The local version feature does not seem to work as documented in https://sdkman.io/usage#localversion
I tried sdk install groovy 2.4.13 /usr/local/src/groovy-2.4.13 from a local version. Instead of linking (or even copying) the existing installation, sdkman downloaded and installed a new copy of 2.4.13 in candidates/groovy/2.4.13/
I tried several other versions of Groovy, Java, etc....same problem.
Also, I note the help for sdk install does not list a possible 4th argument to an existing path.
Currently trying this with version SDKMAN 5.7.3+337

Local feature works a charm for me on macOS!

sdk install java 7 /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/

SDKMAN 5.7.3+337

@hickst It certainly is working. Try using a version that is unique. I think 2.4.13 is taken, so maybe try something like 2.4.13-local.

Success! Thanks for clarifying how it works. The fact that you cannot use the same name as sdkman really should be in the documentation, though. Otherwise, the natural tendency is to follow the naming pattern used by the tool, which results in the failure to create a local link. Also, the help documentation for the install command should be updated to show the optional 4th argument (the existing installation path). Thanks again.

Even better, maybe sdkman itself should tell you that it is a reserved version string. Wdyt?

@marc0der Yes, having the tool itself help one to do it correctly definitely sounds like the best idea.

I also recommend a "local" Java example in the documentation, similar to the one @martin-walsh showed above (thanks for the help @martin-walsh!)

@hickst afaik, it is already documented.

Regarding letting the tool itself help you do it correctly, want to raise a PR for that one?

@marc0der which "it" is already documented? In the documentation for Install Local Version(s), I see only a single Groovy example. I am recommending that:

  1. we add text, in that section, to clarify that the "local" name one selects may not be the same as any version that sdkman already uses,
  2. we add a Java example, similar to the one given above. For example:
    sdk install java 10-zulu-local /Library/Java/JavaVirtualMachines/zulu-10.jdk/Contents/Home
  3. we update the sdkman usage (help) strings to show the optional 4th argument. For example:
commands:
       install   or i    <candidate> [version]
...

would become

commands:
       install   or i    <candidate> [version] [path-to-local-installation]
...

@marc0der I would be happy to open a new issue but do we need to move this discussion to Gitter before I am allowed to do that?

Don't worry about the gitter discussion. You can update the website docs in this project with a PR:
https://github.com/sdkman/sdkman-website

Of course the help can be updated in this project.

May I also suggest an unset option, for those packages which don't have system artifacts?

E.g.
sdk unset grails to effectively unlink any version of grails that's currently configured, but lasts beyond the current shell and doesn't force me to uninstall the various versions installed?

@jamesdh that might be confusing for users as the set command is used for changing versions in the current shell only.

@marc0der isn't that use?

In any case, it'd be nice to somehow remove any link to an installed version without actually uninstalling.

@jamesdh yes you're right, my bad.

I would also like to express my support for this functionality.

I've installed graalvm with sdk to play around with native compilation.
However, on (nodejs) project was failing to build with graal's node .
The only way I could get past this was to uninstall graalvm.

If there was an option to disable/unset sdk graal then I could have avoided the un-instalation.

I do hope sdkman implements this functionality. It is necessary.

@ieugen a better workaround is probably to install the default JDK (AdoptOpenJDK) and make that your system default. Then you shouldn't have any conflicts with Node. You can then apply the sdk use command to switch to Graal in individual terminals when you require it. Hope that helps!

Thanks that is a good suggestion. I do have an issue with it. I already have adoptopenjdk installed via Debian package system. I do prefer that since I have unattended-upgrades in place.
In this case I might go for this workaround if I can use both and experiment.
I do prefer Debian packages since they are better integrated with the system.

Some feedback. The sdk use java XXX method works. However I still need to keep the java version installed in Debian since I have other packages that depend on it.

This does/can create some issues:

  • I have duplicate versions installed, which I should not have
  • I have multiple versions in use at the same time (at least some tooling of the other JDK might not be shadowed). This could lead to subtle bugs if I use adoptopenjdk from sdkman and some tooling from the Debian version of adoptopenjdk .
Was this page helpful?
0 / 5 - 0 ratings