Modern Java in Action

Developer Advocate

Java Team at Oracle

Let’s get started!

Crawling GitHub

Starting with a seed URL:

  1. connect to URL

  2. identify kind of page

  3. identify interesting section

  4. identify outgoing links

  5. for each link, start at 1.

Crawling GitHub

Then:

  1. print statistics

  2. print page list

  3. show pages on localhost

Gameplan

Domain model:

  • create with records and sealed interfaces

  • operate on with pattern matching

Fetching pages:

  • HTTP client to fetch from GitHub

  • virtual threads via structured concurrency

Gameplan

Present results:

  • format with text blocks and string templates

  • host with simple file server

(And modules for reliability.)

Code!

Review

What Java was That?!

JDK 23 with preview features.

Features that aren’t final in JDK 21:

Domain Model

public sealed interface Page
		permits ErrorPage, SuccessfulPage {

	URI url();

}

Domain Model

public record GitHubPrPage(
	URI url, String content, Set<Page> links, int number)
	implements GitHubPage {

	public GitHubPrPage {
		// argument validation
	}

	public GitHubPrPage(
			URI url, String content, int number) {
		this(url, content, new HashSet<>(), number);
	}

	// `equals` and `hashcode` based on `url`

}

Operations

public static String pageName(Page page) {
	return switch (page) {
		case ErrorPage(var url, _)
			-> "💥 ERROR: " + url.getHost();
		case ExternalPage(var url, _)
			-> "💤 EXTERNAL: " + url.getHost();
		case GitHubIssuePage(_, _, _, int number)
			-> "🐈 ISSUE #" + number;
		case GitHubPrPage(_, _, _, int number)
			-> "🐙 PR #" + number;
	};
}

HTTP Client

// creation
var client = HttpClient.newHttpClient();

// use
var request = HttpRequest
	.newBuilder(url)
	.GET()
	.build();
return client
	.send(request, BodyHandlers.ofString())
	.body();

Structured Concurrency

try (var scope =
		new StructuredTaskScope.ShutdownOnFailure()) {
	var futurePages = links.stream()
		.map(link -> scope.fork(
			() -> createPage(link, depth)))
		.toList();

	scope.join();
	scope.throwIfFailed();

	return futurePages.stream()
		.map(Subtask::get)
		.collect(toSet());
} catch (ExecutionException ex) {
	// [...]
}

Simple File Server

SimpleFileServer.createFileServer(
		address,
		serverDir.toAbsolutePath(),
		OutputLevel.INFO)
	.start();

Source-Code Programs

java -p jars $mainClass $args

JPackage

Let’s watch Jose’s exploration…​

Modern Java In Action

  • great domain modeling with
    records, sealed classes, pattern matching

  • easy, structured (and scalable) concurrency

  • on-board HTTP client and simple web server

  • easy experimentation and packaging

So long…​

37% off with
code fccparlog

bit.ly/the-jms

More

Slides at slides.nipafx.dev
⇜ Get my book!

Follow Nicolai

nipafx.dev
/nipafx

Follow Java

inside.java // dev.java
/java    //    /openjdk

Image Credits