Context in Fortress

Here’s the translation of the Go code to Java, with explanations in Markdown format suitable for Hugo:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

public class Context {

    public static void main(String[] args) throws IOException {
        // As before, we register our handler on the "/hello" route, and start serving.
        HttpServer server = HttpServer.create(new InetSocketAddress(8090), 0);
        server.createContext("/hello", new HelloHandler());
        server.setExecutor(Executors.newCachedThreadPool());
        server.start();
        System.out.println("Server started on port 8090");
    }

    static class HelloHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            System.out.println("server: hello handler started");

            // In Java, we don't have a direct equivalent to Go's context.
            // We can use Thread interruption for a similar effect.
            Thread currentThread = Thread.currentThread();

            new Thread(() -> {
                try {
                    Thread.sleep(10000); // Wait for 10 seconds
                    if (!currentThread.isInterrupted()) {
                        String response = "hello\n";
                        exchange.sendResponseHeaders(200, response.length());
                        exchange.getResponseBody().write(response.getBytes());
                        System.out.println("Response sent");
                    }
                } catch (InterruptedException | IOException e) {
                    System.out.println("server: " + e.getMessage());
                } finally {
                    exchange.close();
                    System.out.println("server: hello handler ended");
                }
            }).start();

            // Simulate cancellation after 5 seconds
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                    currentThread.interrupt();
                    System.out.println("server: request cancelled");
                    String errorMessage = "Request cancelled";
                    exchange.sendResponseHeaders(500, errorMessage.length());
                    exchange.getResponseBody().write(errorMessage.getBytes());
                } catch (InterruptedException | IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

In the previous example, we looked at setting up a simple HTTP server. HTTP servers are useful for demonstrating the usage of cancellation and timeout mechanisms. While Java doesn’t have an exact equivalent to Go’s context.Context, we can achieve similar functionality using thread interruption.

A key difference in Java is that we don’t have a built-in context system like Go. Instead, we use thread interruption to signal cancellation. The HttpExchange object provides request-scoped information.

In the HelloHandler:

  1. We print a message when the handler starts and use a finally block to ensure we print when it ends.

  2. We create a new thread to simulate some work the server is doing. This thread waits for 10 seconds before sending a reply to the client.

  3. We create another thread to simulate a cancellation after 5 seconds. This thread interrupts the main handler thread and sends an error response.

  4. If the handler thread is not interrupted after 10 seconds, it sends the “hello” response.

To run the server:

$ javac Context.java
$ java Context

This will start the server on port 8090. You can then simulate a client request:

$ curl localhost:8090/hello

If you let it run for the full 10 seconds, you’ll see the “hello” response. If you interrupt it (e.g., by pressing Ctrl+C in the terminal running curl) before 10 seconds, you’ll see the cancellation message.

This example demonstrates how to handle long-running operations in an HTTP server context, including the ability to cancel requests. While the implementation differs from Go, the core concepts of managing request lifecycles and handling cancellations remain the same.