# Io / Github / Biezhi / Java11

## Overview

This module is a collection of educational examples that showcase the new language and standard library features introduced in **JDK 11**. Specifically, it serves as a practical reference for developers transitioning from legacy Java networking approaches (such as `java.net.URL` and `HttpURLConnection`) to the modern, builder-based APIs introduced in Java 11.

The module is **not a library or framework** — it is a playground class suite. Each example class demonstrates a distinct pattern, and individual methods can be uncommented in the `main()` entry point for interactive experimentation.

At the time of indexing, the only child module under this package is **http**, which focuses entirely on Java 11's `java.net.http` client API.

---

## Sub-module Guide

### http

The `http` sub-module contains the `Example` class, which provides ten distinct methods covering the full surface area of the Java 11 HTTP Client:

| Method | Pattern | Description |
|--------|---------|-------------|
| `syncGet` | Synchronous GET | Blocking request with response body as a String |
| `asyncGet` | Asynchronous GET | Non-blocking request with `CompletableFuture` |
| `asyncPost` | Asynchronous POST | Sends JSON body (serialized via Gson) to a target URL |
| `downloadFile` | File download | Streams HTTP response body directly to a temp file on disk |
| `uploadFile` | File upload | Streams a local file into a POST request body via `BodyPublishers.ofFile()` |
| `proxy` | Proxy configuration | Routes traffic through a `ProxySelector` |
| `basicAuth` | Basic authentication | Supplies credentials via a custom `Authenticator` |
| `http2` | HTTP/2 protocol | Uses HTTP/2 over TLS for request/response |
| `getURIs` | Parallel fan-out | Executes multiple async requests concurrently via `CompletableFuture.allOf()` |
| `main` | Entry point | Playground runner — all example calls are commented out except `asyncPost()` |

Together these methods demonstrate the complete request lifecycle: client creation, request building, body publishing, response handling, and error recovery — both synchronously and asynchronously.

---

## Key Patterns and Architecture

### Typical Request Lifecycle

The HTTP examples follow a consistent builder pattern:

```mermaid
flowchart TD
    A["Example.syncGet(uri)"] --> B["HttpClient.newHttpClient()"]
    B --> C["HttpRequest.newBuilder().uri(...).build()"]
    C --> D["client.send(request, ofString())"]
    D --> E["HttpResponse<String>"]
    E --> F["Print status + body"]
```

1. A default `HttpClient` is created with `HttpClient.newHttpClient()`.
2. An `HttpRequest` is built via the builder pattern, setting the target URI, headers, and body.
3. `client.send()` is called with the request and a body handler (e.g., `BodyHandlers.ofString()`).
4. The `HttpResponse` object is returned, providing access to the status code, headers, and body.

### Asynchronous Request Flow

For async operations, the pattern shifts to `CompletableFuture`-based non-blocking execution:

```mermaid
sequenceDiagram
    participant Caller
    participant Client as HttpClient
    participant Future as CompletableFuture
    participant Handler as whenComplete callback
    Caller->>Client: sendAsync(request, handler)
    Client-->>Future: returns immediately
    Note over Future: background thread performs HTTP call
    alt Success
        Client->>Handler: invoke with response, null
        Handler->>Handler: print body and status
    else Error
        Client->>Handler: invoke with null, exception
        Handler->>Handler: print stack trace
    end
    Handler->>Caller: join() returns
```

This pattern replaces the legacy callback-based approaches (such as `AsyncHttpClient`) with a cleaner, composable API using the standard `CompletableFuture`.

### Parallel Fan-out

The `getURIs()` method demonstrates the idiomatic Java 11 pattern for executing multiple HTTP requests concurrently:

```mermaid
flowchart LR
    A["List<URI> uris"] --> B["Stream.map(newBuilder)"]
    B --> C["List<HttpRequest>"]
    C --> D["Stream.map(sendAsync)"]
    D --> E["List<CompletableFuture>"]
    E --> F["CompletableFuture.allOf()"]
    F --> G[".join() — all complete"]
```

Each URI is converted to a `HttpRequest`, each request is fired asynchronously on the client's internal executor, and `CompletableFuture.allOf()` creates a combined future that completes when all individual requests are done. This is the preferred approach over manually spawning threads for concurrent HTTP calls.

---

## Dependencies and Integration

### External Dependencies

| Dependency | Use |
|------------|-----|
| `com.google.gson.Gson` | Serializes `Foo` POJOs to JSON strings for POST request bodies |

### JDK 11 Built-in APIs Used

| API | Class | Purpose |
|-----|-------|---------|
| `java.net.http.HttpClient` | `HttpClient` | HTTP client for sending requests |
| `java.net.http.HttpRequest` | `HttpRequest` | Builder for HTTP requests (method, URI, headers, body) |
| `java.net.http.HttpResponse` | `HttpResponse<T>` | Response envelope with status, headers, and typed body |
| `java.net.http.HttpRequest.BodyPublishers` | Static utility | Creates body publishers from `String`, `Path`, `InputStream`, `byte[]`, etc. |
| `java.net.http.HttpResponse.BodyHandlers` | Static utility | Converts response streams into `String`, `Path`, `byte[]`, etc. |
| `java.util.concurrent.CompletableFuture` | `CompletableFuture<T>` | Async result wrapper for non-blocking requests |

### Internal Relationships

```mermaid
flowchart TD
    E["Example<br/>10 example methods"]
    F["Foo<br/>POJO payload"]
    E -->|"Gson.toJson()"| F
```

The `Example` class is the sole consumer of the `Foo` class. The `Foo` instance is serialized with Gson and sent as the body of the `asyncPost()` method. `Foo` is a minimal POJO with two `String` fields (`name` and `url`) and no methods — it exists solely as a JSON serialization target.

---

## Notes for Developers

- **Playground class**: The `main()` method has all example calls commented out except `asyncPost()`. This is clearly intended for interactive experimentation — uncomment individual method calls to test different patterns.

- **Default client behavior**: `HttpClient.newHttpClient()` creates a client that:
  - Follows `GET` and `HEAD` redirects automatically.
  - Uses HTTP/1.1 by default (set `.version(HttpClient.Version.HTTP_2)` for HTTP/2).
  - Has no timeout set — consider using `.connectTimeout(Duration.ofSeconds(10))` for production use.

- **Gson dependency**: The `asyncPost()` method requires `com.google.gson.Gson` on the classpath. If the Gson dependency is removed, the POST example will not compile.

- **Hardcoded credentials**: The `basicAuth()` method embeds credentials (`"username"`, `"password"`) directly in the code. In a real application, these should come from environment variables, a secrets manager, or a configuration file.

- **Hardcoded URLs**: All target URLs (`httpbin.org`, `labs.consol.de`, `localhost:8080`) are hardcoded. For production use, externalize these to configuration.

- **Resource cleanup**: `HttpClient` does not need explicit cleanup in modern Java. However, if you create many clients over the lifetime of a long-running application, consider reusing a single `HttpClient` instance (it is thread-safe) rather than calling `newHttpClient()` repeatedly.

- **Thread safety**: `HttpClient`, `HttpRequest`, and `HttpResponse` instances are thread-safe. `CompletableFuture` instances returned by `sendAsync()` are also thread-safe. You can safely share clients across threads.

- **HTTP/2 caveat**: HTTP/2 support requires a JDK built with an SSL provider that supports HTTP/2 (e.g., Oracle JDK or OpenJDK with the built-in TLS implementation). This may not be available in all JDK distributions.
