# Windows — JDK 21 + Maven + JAVA_HOME

The single most common Lab 6 / Spring Boot blocker on Windows is a broken `JAVA_HOME` or `PATH`. This guide takes you from a clean Windows install to a working `mvn -version` showing **Java 21**.

> **Pick your path:** if you have Windows 11 (or Windows 10 with App Installer), use [Path A — winget](#path-a--winget-one-liner-fastest). Otherwise use [Path B — manual installers](#path-b--manual-installers).
>
> When in doubt, start with Path A. Jump to [verification](#5-verify-everything-works) at the end of either path.

---

## What you need at the end

```powershell
java -version
# openjdk version "21.0.x" 2024-xx-xx

mvn -version
# Apache Maven 3.9.x
# Java version: 21.0.x, vendor: Eclipse Adoptium

echo $env:JAVA_HOME
# C:\Program Files\Eclipse Adoptium\jdk-21.0.x.X-hotspot
```

If all three commands work in a fresh PowerShell window, you're done.

---

## Path A — winget (one-liner, fastest)

### 1. Open PowerShell as Administrator

Press <kbd>Win</kbd>, type **"powershell"**, right-click → **Run as administrator**.

### 2. Install JDK 21 and Maven

```powershell
winget install --id EclipseAdoptium.Temurin.21.JDK
winget install --id Apache.Maven
```

> 💡 **What just happened.** winget pulled the official **Temurin (Eclipse Adoptium) JDK 21** and **Apache Maven** installers, ran them, and added the JDK to `PATH` automatically. **Maven from winget does NOT set `JAVA_HOME`** for you, and **older Temurin installers also skip it** — that's the actual bug behind 90 % of the lab failures.

### 3. Set `JAVA_HOME` manually

Find your exact JDK install path:

```powershell
Get-ChildItem 'C:\Program Files\Eclipse Adoptium'
```

You'll see something like `jdk-21.0.4.7-hotspot`. Copy that folder name, then:

```powershell
[Environment]::SetEnvironmentVariable(
    'JAVA_HOME',
    'C:\Program Files\Eclipse Adoptium\jdk-21.0.4.7-hotspot',
    'Machine'
)
```

> 💡 **Why `'Machine'`?** That writes it to the *system* environment so every user and every shell sees it. `'User'` would limit it to the current Windows user — fine for a personal laptop, but inconsistent if you ever switch accounts.

### 4. Add the JDK `bin` to `PATH`

The winget installer usually does this, but verify:

```powershell
$javaBin = "$env:JAVA_HOME\bin"
$current = [Environment]::GetEnvironmentVariable('Path', 'Machine')

if ($current -notlike "*$javaBin*") {
    [Environment]::SetEnvironmentVariable(
        'Path', "$current;$javaBin", 'Machine'
    )
    Write-Host "Added $javaBin to system PATH"
} else {
    Write-Host "Already on PATH"
}
```

### 5. **Close PowerShell and open a new window** (Administrator no longer needed)

Environment variables only take effect in **new** processes. Skip this and `java -version` will keep showing the old value.

Jump to [verification](#5-verify-everything-works).

---

## Path B — Manual installers

Use this if you're on Windows 10 without winget, behind a corporate proxy, or you prefer GUI installers.

### 1. Download the JDK

Go to <https://adoptium.net/temurin/releases/?version=21&os=windows>.

Pick:
- **Version**: 21 - LTS
- **Operating System**: Windows
- **Architecture**: x64
- **Package Type**: JDK
- **Installer**: `.msi`

Click the `.msi` link, run it.

In the installer, on the "Custom Setup" screen, **expand every option** and choose **"Will be installed on local hard drive"** for:

- ✅ `Set JAVA_HOME variable`
- ✅ `JavaSoft (Oracle) registry keys`
- ✅ `Associate .jar`

If you only check `JAVA_HOME`, the rest still work — but ticking all three saves headaches later.

> 💡 **Why this matters.** If you don't tick `Set JAVA_HOME variable`, the installer skips it and you'll set it by hand below. Not the end of the world — just an extra step.

### 2. Download Maven

Go to <https://maven.apache.org/download.cgi>.

Under **Files**, click **Binary zip archive** (e.g. `apache-maven-3.9.9-bin.zip`).

### 3. Install Maven (it's just an unzip)

Right-click the zip → **Extract All...** → extract to:

```
C:\Program Files\Apache\
```

You should now have:

```
C:\Program Files\Apache\apache-maven-3.9.9\
├── bin\
├── boot\
├── conf\
└── lib\
```

> 💡 **Why a non-user folder?** Putting it in `C:\Program Files\Apache\` makes it a system-wide install. If you put it under `C:\Users\YourName\` only your account can run it.

### 4. Set environment variables in the GUI

This is the place students get lost. Take it slow.

1. Press <kbd>Win</kbd>, type **"environment variables"**, click **"Edit the system environment variables"**.
2. Click the **"Environment Variables…"** button at the bottom right.
3. In the **lower** box ("System variables"), click **New…**:

   - **Variable name**: `JAVA_HOME`
   - **Variable value**: `C:\Program Files\Eclipse Adoptium\jdk-21.0.4.7-hotspot`
   - *(Use the actual folder name on your machine — open `C:\Program Files\Eclipse Adoptium\` and copy it.)*
   - Click **OK**.

4. Still in the lower box, click **New…** again:

   - **Variable name**: `MAVEN_HOME`
   - **Variable value**: `C:\Program Files\Apache\apache-maven-3.9.9`
   - Click **OK**.

5. Still in the lower box, scroll to find **`Path`**, select it, click **Edit…**, then **New** and add **two** entries:

   ```
   %JAVA_HOME%\bin
   %MAVEN_HOME%\bin
   ```

   Click **OK** on every dialog to close all of them.

> ⚠️ **Edit "System variables", not "User variables".** They're two separate boxes in the same dialog. Setting them under "User variables" works for one account; "System variables" works for everyone.

### 5. **Close every PowerShell / CMD window and open a new one**

Same rule as Path A — env vars only apply to new processes. Some Windows 10 builds also need a sign-out / sign-in for VS Code and IntelliJ to pick up the change.

---

## 5. Verify everything works

Open a **fresh** PowerShell (or CMD) and run all four:

```powershell
java -version
javac -version
mvn -version
echo $env:JAVA_HOME
```

You should see:

```
openjdk version "21.0.4" 2024-xx-xx
javac 21.0.4
Apache Maven 3.9.9 (...)
Maven home: C:\Program Files\Apache\apache-maven-3.9.9
Java version: 21.0.4, vendor: Eclipse Adoptium, runtime: C:\Program Files\Eclipse Adoptium\jdk-21.0.4.7-hotspot
C:\Program Files\Eclipse Adoptium\jdk-21.0.4.7-hotspot
```

If any of those four show a different number or fail, scroll to [Troubleshooting](#troubleshooting).

### Quick Maven sanity test

This actually downloads dependencies and runs a tiny Spring Boot starter — proves Maven, Java, and your network all work together.

```powershell
mkdir C:\temp\mvntest
cd C:\temp\mvntest
mvn archetype:generate -DgroupId=hello -DartifactId=hello -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd hello
mvn -q -DskipTests compile
```

If the last command finishes silently, you're fully set up. Delete the folder when done:

```powershell
cd ..\..
Remove-Item -Recurse -Force C:\temp\mvntest
```

---

## Troubleshooting

### `'java' is not recognized as an internal or external command`

`PATH` isn't picking up Java.

```powershell
# In a NEW PowerShell:
echo $env:Path
```

Look for `...jdk-21...\bin`. If it's missing, you didn't add it (Path A step 4 or Path B step 4). If it's there but Java still can't be found, the folder name in `JAVA_HOME` is wrong — re-check with:

```powershell
Get-ChildItem 'C:\Program Files\Eclipse Adoptium'
```

…and use the exact folder name shown.

### `java -version` shows the wrong version (e.g. Java 8 or 17)

You have another JDK earlier on `PATH`. Find them all:

```powershell
where.exe java
```

If multiple lines come back, the **first** one wins. Remove the unwanted ones from `PATH`, or put `%JAVA_HOME%\bin` ahead of them in the system Path editor.

### `mvn -version` shows the wrong Java

Maven uses `JAVA_HOME`, not `PATH`. So if Maven reports e.g. Java 17 while `java -version` reports 21, `JAVA_HOME` is still pointing at the old JDK.

```powershell
echo $env:JAVA_HOME
# Should print the JDK 21 path, not 17
```

If it's wrong, repeat Path A step 3 (or Path B step 4), then **open a brand-new shell**.

### `'mvn' is not recognized…`

Same as Java — `%MAVEN_HOME%\bin` isn't on `PATH`. Re-check Path B step 4, or for Path A confirm winget actually installed Maven:

```powershell
winget list Apache.Maven
```

### Environment variables look right but PowerShell ignores them

PowerShell caches env vars per process. The fix is always **close every shell and open a new one**. If even that doesn't work, sign out of Windows and back in.

### IntelliJ / VS Code uses the wrong JDK

GUIs cache `JAVA_HOME` from whenever they were started.

- **IntelliJ IDEA:** **File → Project Structure → Project → SDK** → set explicitly to JDK 21.
- **VS Code:** Restart it after changing env vars. If still wrong, set `java.jdt.ls.java.home` in Settings to the JDK 21 install path.

### Behind a corporate / university proxy → `mvn` can't download anything

Edit (or create) `C:\Users\YourName\.m2\settings.xml`:

```xml
<settings>
  <proxies>
    <proxy>
      <id>uniproxy</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>proxy.suza.ac.tz</host>
      <port>8080</port>
      <username>YOURUSER</username>
      <password>YOURPASS</password>
      <nonProxyHosts>localhost</nonProxyHosts>
    </proxy>
  </proxies>
</settings>
```

Replace host/port with the values from the IT department.

### `winget` itself doesn't exist

You're on an older Windows 10 build. Either:

- Install "App Installer" from the Microsoft Store (that ships `winget`), or
- Use [Path B — manual installers](#path-b--manual-installers).

### Windows Defender blocks the installer

Right-click the `.msi` → **Properties** → tick **Unblock** at the bottom → **Apply**. Then re-run.

### Still stuck?

Bring your laptop to lab. Don't fight env vars alone for hours — they're a known time sink and we have a checklist that resolves 95 % of cases in 5 minutes.

---

## Why we need all this

| Thing       | What it does                                              | Why it's required |
|-------------|-----------------------------------------------------------|-------------------|
| **JDK 21**  | Compiles and runs Java code                               | Spring Boot 3 requires Java 17+; we standardise on 21 |
| **Maven**   | Downloads dependencies, builds the project                | `mvn spring-boot:run` is how we start the app |
| **`JAVA_HOME`** | Tells Maven (and IntelliJ, VS Code, Gradle, ...) **which** JDK to use | Without it, Maven uses whatever `java` it finds on `PATH` — which might be Java 8 from another install |
| **`PATH`**  | Tells the shell which folders to search for executables   | Without `%JAVA_HOME%\bin` and `%MAVEN_HOME%\bin` on PATH, the commands don't exist |

You only set this up **once per machine**. After that, every Spring Boot lab Just Works.
