Linux Java Development on Windows (WSL) - sorc-lab/wiki-developer GitHub Wiki

deploy/debug java code on a remote server using Intellij: https://stackoverflow.com/questions/42380496/deploy-debug-java-code-on-a-remote-server-using-intellij/42392922#42392922

Using IntelliJ with Windows Subsystem for Linux 2: https://www.tomaszmik.us/2020/01/26/intellij-on-wsl/

windows 10, intellij idea ultimate and wsl: https://github.com/netdisco/netdisco/wiki/windows-10,-intellij-idea-ultimate-and-wsl

How to make Intellij Idea Windows font to look like Mac OS X: https://www.youtube.com/watch?v=X6txCbt2nFA

YT Setup guide (non-IntelliJ): https://www.youtube.com/watch?v=-atblwgc63E

Wiki vs gh-pages: https://stackoverflow.com/questions/31969868/how-to-store-github-wiki-as-part-of-source

Check WSL version and install WSL2
wsl -l -v (in PowerShell). If it returns errors, then WSL1 is installed. Uninstall (???) and install WSL2 https://scotch.io/bar-talk/trying-the-new-wsl-2-its-fast-windows-subsystem-for-linux

Convert existing WSL1 Ubuntu installed to WSL2 wsl --set-version <Linux Distro name> 2 (NOTE: You see installed distros via wsl -l -v in Windows cmd prompt) NOTE: Inside WSL2 linux cmd prompt you can exec explorer.exe . and it will popup a Windows file explorer window. WSL2 uses Hyper-V to run the actual linux kernel inside windows, not just in a compatability layer/subsystem like in WSL1. WSL2 uses a virtual hard disk and does not have to do any NTFS conversion or whatever when reading and writing files. For this reason, it is more performant, especially if files that are read and written to exist in the WSL2 root filesystem.

Install WSL2

Follow Windows instructions. 2020/04/18 required to be a member of Windows Insider program. Test correct Windows version in command prompt: ver -> should return Microsoft Windows [Version 10.0.19041.207] (Note: Need to research minimum version for WSL2)

Check existing WSL2 installed distros: wsl -l -v Should return a list:

PS C:\WINDOWS\system32> wsl -l -v
  NAME            STATE           VERSION
* Legacy          Stopped         1
  Ubuntu-18.04    Stopped         1

Note: Set version command didn't work at time of writing this.

Uninstall existing distros (upgrade command doesn't work)

Search "Ubuntu" in windows, Rclick -> Uninstall (if previously installed this way) Check that it was removed from WSL2

Set WSL2 to be the default architecture: wsl --set-default-version 2 Returned: Please enable the Virtual Machine Platform Windows feature and ensure virtualization is enabled in the BIOS. For information please visit https://aka.ms/wsl2-install

Run in PowerShell -> Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform (requires restart)

Note: Running the set default command returned this after restart: WSL 2 requires an update to its kernel component. For information please visit https://aka.ms/wsl2kernel

Google WSL2 update and download the update .exe file from Windows. wsl_update_x64.exe

Note: wsl -l -v is same as wsl --list --verbose

Search windows for "ubuntu" and install.

Full Ubuntu on WSL install instructions: https://wiki.ubuntu.com/WSL

Use wiki link for Ubuntu 18.04 LTS from Microsoft store.

Launch ubuntu to test it.

Set Ubuntu 18 as WSL2 default distro/VM: wslconfig /setdefault Ubuntu-18.04

VS Code

Best way to install WSL2 VS code and run it: cd ~ code . Above instructions will cause ubuntu to automatically install vs code and launch it. Once vs code boots up, press Ctrl + ~ to get better command prompt than default Ubuntu one that comes with windows.

TODO: Follow these links to sort out a temporary work around to handle IntelliJ lack of WSL2 support
https://stackoverflow.com/questions/52852105/should-i-tell-intellij-that-my-wsl-filesystem-is-case-sensitive
Also, https://www.reddit.com/r/bashonubuntuonwindows/comments/76sn72/should_i_work_with_intellij_on_wsl/

NOTE: Install Visual Studio Code Remote - WSL extension or any other recommended extensions in VSCode pop ups

WSL2 Java Dev. Env

Upgrade Ubuntu 18 to 19

$ sudo apt update 
$ sudo apt upgrade
$ sudo apt dist-upgrade

$ sudo apt autoremove

Configure the release upgrader. Open and edit the /etc/update-manager/release-upgrades file and ensure that the Prompt variable is set to normal.

# Default behavior for the release upgrader.

[DEFAULT]
# Default prompting behavior, valid options:
#
#  never  - Never check for a new release.
#  normal - Check to see if a new release is available.  If more than one new
#           release is found, the release upgrader will attempt to upgrade to
#           the release that immediately succeeds the currently-running
#           release.
#  lts    - Check to see if a new LTS release is available.  The upgrader
#           will attempt to upgrade to the first LTS release available after
#           the currently-running one.  Note that this option should not be
#           used if the currently-running release is not itself an LTS
#           release, since in that case the upgrader won't be able to
#           determine if a newer release is available.
Prompt=normal

$ sudo do-release-upgrade
NOTE: This runs into an issue with not being able to connect to snap store. This is a known WSL issue. Follow below 
      instructions to get around this.

1. Abort the do-release-upgrade script
2. Re-launch Ubuntu
3. Remove lxd with: sudo dpkg --force depends -P lxd; sudo dpkg --force depends -P lxd-client
4. Finish with sudo apt upgrade
NOTE: Upgrade hung at 98% "Installing new version of config file /etc/lvm/lvm.conf ..."
      Search Ubuntu in windows search start menu. Select Ubuntu LTS -> App Settings -> Repair.
      Re-ran the upgrade and it didn't error out. cat /etc/os-release shows 19.10 and everything seems fine.

Install OpenJDK 13

$ sudo apt-get update -y && sudo apt-get upgrade -y

$ sudo apt install openjdk-13-jdk

$ java -version
openjdk version "13" 2019-09-17
OpenJDK Runtime Environment (build 13+13-Ubuntu-0ubunt1)
OpenJDK 64-Bit Server VM (build 13+13-Ubuntu-0ubunt1, mixed mode, sharing)

$ sudo update-alternatives --config java
There are 2 choices for alternative java (providing /usr/bin/java).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-13-openjdk-amd64/bin/java 1211 auto mode
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 manual mode
2 /usr/lib/jvm/java-13-openjdk-amd64/bin/java 1211 manual mode

$ export JAVA_HOME=/usr/lib/jvm/java-13-openjdk-amd64/bin/java

$ echo $JAVA_HOME
/usr/lib/jvm/java-13-openjdk-amd64/bin/java

$ vim ~/.bashrc
Add this line: export JAVA_HOME=/usr/lib/jvm/java-13-openjdk-amd64/jre/bin/java
then, run: $ source ~/.bashrc

$ echo $JAVA_HOME
/usr/lib/jvm/java-13-openjdk-amd64/jre/bin/java

Install Maven

$ sudo apt install maven
$ mvn -version

NOTE: JAVA_HOME should point to a JDK not a JRE Fix $JAVA_HOME from recent configuration: $JAVA_HOME/bin/javac -version should return "javac 1.X.0_XX" not: "No such file or directory" Set ~/.bashrc $JAVE_HOME path to export JAVA_HOME=/usr/lib/jvm/java-13-openjdk-amd64 Should allow maven to run via mvn -version

NOTE: Maven seems to be using its previously installed version on /mnt/c/Program Files which will cause it to run slowly, and ideally we don't want anything running on Windows unless we have to. Need to fix its path somehow.

Uninstall Windows version of Maven. Find where maven version on WSL is installed, if it exists, or follow these instructions to install manually in opt: https://www.vultr.com/docs/how-to-install-apache-maven-on-ubuntu-16-04?gclid=CjwKCAjwkPX0BRBKEiwA7THxiPkVW-rwrNXvYTZdOx73-GMbrlJ8ZMpGvZPEDHv9Cfs0PYjsAOW69xoCwBcQAvD_BwE

NOTE: Logged back in a day later and maven fixed itself. It's pointing at its own WSL2 version now:

sorc@SORC-WORK01:/mnt/d$ mvn -version
Apache Maven 3.6.1
Maven home: /usr/share/maven
Java version: 13, vendor: Private Build, runtime: /usr/lib/jvm/java-13-openjdk-amd64
Default locale: en, platform encoding: UTF-8
OS name: "linux", version: "4.19.84-microsoft-standard", arch: "amd64", family: "unix"

Create case-sensitive directory on Windows

Create case-sensitive directory on Windows mounted drive, not WSL2 root file system. (bad but no other option since IntelliJ lacks WSL2 support like VS Code has.)

NOTE: Test if /mnt/<drive> is case-sensitive already. mkdir tmp, then try to mkdir TMP and if it says directory already exists, then it's not case-sensitive

below taken from https://devblogs.microsoft.com/commandline/per-directory-case-sensitivity-and-wsl/ --------------------------------------------------------------------------------------------------------------------- The Windows Subsystem for Linux uses another mechanism, which itself bypasses that registry key, allowing us to perform case sensitive file system operations. This is what allows Linux applications running in WSL to use file names that differ only by case, just like they can on real Linux, even with that global registry key set.

Unfortunately, this leaves you with files that can’t be accessed by Windows applications. While you could change the global registry key, that still would only work for those applications that use FILE_FLAG_POSIX_SEMANTICS, and this would change the behavior for all files on all drives, which may not be intended and may break some applications. ---------------------------------------------------------------------------------------------------------------------

Check if directory is case-sensitive:

fsutil.exe file queryCaseSensitiveInfo /mnt/d/VM
Case sensitive attribute on directory D:\VM is disabled.

fsutil.exe file setCaseSensitiveInfo sorc-lab enable

Link explains how to set WSL config to set default values when creating dirs: https://devblogs.microsoft.com/commandline/per-directory-case-sensitivity-and-wsl/

For this example, I just want one case-sensitive directory that I will put all projects in so for me this is just a one time thing and won't need a global config setting for future directories, because all directories created in the sorc-lab directory will automatically be case-sensitive anyways.

NOTE: I will also not be accessing this directory from Windows, but I will be opening these files in IntelliJ.

Configure WSL2 to allow Windows to keep the Linux permissions set within WSL2 environment.

Run the following commands for all mounted drives on Windows:

sudo umount /mnt/c
sudo mount -t drvfs C: /mnt/c -o metadata

Test that it worked via: mount -l

C: on /mnt/c type 9p (rw,relatime,dirsync,aname=drvfs;path=C:;metadata;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=3,wfd=3)

Should be able to see the metadata keyword in the output above. Note: The above mount commands will not work within VS Code terminal, must run within the WSL terminal only.

Edit wsl.conf file (probably doesn't exist, so create it with sudo vim /etc/wsl.conf):

[automount]
enabled = true
options = "metadata,umask=22,fmask=11"

Above config will set files to now show up with a comfortable permission setting of 0644 and directories with 0755 if they’re mounted under /mnt.

Read more about wsl.conf from Microsoft to get more info.

Edit ~/.profile so that files and directories are created with default permissions:

if [[ "$(umask)" = "0000" ]]; then
  umask 0022
fi

Without the above profile settings, files will be created with 0666 and directories with 0777 by default.

https://www.turek.dev/post/fix-wsl-file-permissions/ https://devblogs.microsoft.com/commandline/chmod-chown-wsl-improvements/

Configure IntelliJ to use LF instead of CRLF line endings.

To set default line ending for all new files: go to Settings/Preferences | Editor | Code Style and change Line separator (for new files) option to the desired style (e.g. Unix and OS X (\n)).

To change for individual file: File->Line separators, or select in bottom right IDE system tray.

Convert existing dpk-sim project (CRLF) to LF:

sudo apt install dos2unix
find . -type f -exec dos2unix {} \;

Make sure IntelliJ Git root is set to use path to Git in WSL2 and not the Git binary installed on windows Host sytem. Settings->Version Control->Path to Git executable:

NOTE: Not going to cover setting up Windows Git to handle CRLF to LF conversion on commit, because we shouldn't need that ever. With WSL2, all Linux apps will be developed in LF IntelliJ IDE, and Windows apps, ie UE4 C++ projects will want to remain CRLF inside Visual Studio etc, and text editor VS Code can be used in Windows or WSL2 and toggle to whatever it needs for each file specifically.

OPTIONAL: Install IntelliJ plugin Native Terminal. Supports WSL terminal from IDE. I just use VS Code terminal.

TODO: IntelliJ is using Windows Git binary and is showing incorrect files showing as edited when WSL2 Git does not report this. This needs to be solved, but a hack is necessary since IntelliJ doesn't support WSL2 yet.

Potential solutions: https://stackoverflow.com/questions/43666009/using-git-in-windows-subsystem-for-linux-through-intellij

NOTE: The above issue is actually being caused by changing the file permissions in WSL2 and Windows Git bash is detecting that change. I'll solve this on Windows side to get the diff to go away and resolve these issues later. This won't happen (hopefully) on new WSL2 projects under IntelliJ. This needs to be resolved but I'll punt on this as I do not want to introduce more hacks, but IntelliJ should be setup to support WSL2.

NOTE: Explain that IntelliJ will still need to point at a Windows Java 11 install binary, but all builds will be done via WSL2 terminal that runs OpenJDK13 and will be compatible, or shouldn't matter since we will not build within Windows IntelliJ anyways.

TODO: Once this is all done and cleaned up. Figure out how to attach a remote debugger from Windows IntelliJ to WSL2 docker container, if that's possible.

Configure IntelliJ to use OSX-like fonts.

(Make sure this is an improvement of the current font settings): https://www.youtube.com/watch?v=X6txCbt2nFA

Spring Initializr hello world app w/ PostgreSQL docker container

https://start.spring.io/

Maven Project
Spring boot 2.2.6
Group: com.sorclab
Artifact: hello-world
Name: hello-world (same as Artifact usually)
Description: Optional, can be changed later in pom.xml
Package name: com.sorclab.hello-world (this auto fills)
Packaging: Jar
Java versions: Use 11 for now, since there was no Java 13 options. Also windows is running Java 11 version.

Dependencies: Lombok, Spring Web, **NOTE**: PSQL dependencies are unknown, we'll add them to pom.xml manually.

Move hello-world.zip to /mnt/c
unzip it in WSL2 instead of Windows
sudo apt install unzip
unzip hello-world.zip
This will force the use of Linux file permissions and in general a best practice when dealing with WSL2. Do as much within Linux as possible to maintain compatibility and consistency.

Open project in IntelliJ (make sure Java 11 or 13 installed in windows and project struct in IntelliJ point to proper Winsows binary).

Simple to open in IntelliJ. Browse for hello-world and open the pom.xml file within IntelliJ and Open as project

Run in WSL2 to test.

$ cd /mnt/c/sorc-lab/hello-world
$ mvn clean install -DskipTests && mvn spring-boot:run

Should build the jar and spin up the Spring boot app. If successful, will see the following line:
Started HelloWorldApplication in 3.946 seconds (JVM running for 4.618)

Edit pom.xml file and update the java version:

<properties>
    <java.version>13</java.version>
</properties>

Install docker and setup/run PostgreSQL container

https://hub.docker.com/_/postgres

NOTE: At the time of writing this, official Docker docs for installing on Windows 10 gave instructions to download and install Docker for windows and all the installation settings that were needed to integrate with WSL2 were pre-selected by default. You should not have to do anything special other than install the latest Docker for windows executable and install it. Test it in WSL2 via docker run hello-world.

docker ps
docker images
docker rmi <image_id>
docker rm $(docker ps --all -q)
// NOTE: Need container cleanup script

Download PostgreSQL image: docker pull postgres


Configure PostgreSQL w/ docker-compose

  • Hello world via Liquibase + manual docker run psql container cmd
  • Setup dc file
  • Create init script
  • Centralize init scripts and point all future dc files to one db port
  • More docker scripts and ideally a cleanup script

Hello World CRUD operations via Spring Boot REST API

Install psql and PGAdmin

  • Show how to query data in both psql and PGAdmin

Setup remote debugger IntelliJ (Windows) --> WSL2 docker container

https://www.baeldung.com/intellij-remote-debugging

BONUS: Configure IntelliJ fonts and themes

⚠️ **GitHub.com Fallback** ⚠️