A Long Spring: 19 Years of Living with Your Past Mistakes • Arjen Poutsma • GOTO 2025

Arjen Poutsma, a Spring Framework veteran, reflects on 19 years of evolving the framework. He shares insights on API design from XML to functional programming, detailing anecdotes like bubble sort in MVC and the challenges of HTTP method enums. Poutsma emphasizes the critical role of diversity, empathy, humility, and restraint in open-source stewardship to maintain developer trust and foster innovation under constraints.

6 min read
A Long Spring: 19 Years of Living with Your Past Mistakes • Arjen Poutsma • GOTO 2025
source: https://www.youtube.com/watch?v=1o2E2n0KDZ4

Arjen Poutsma, a veteran of the Spring Framework, shares reflections from his 19 years working on the project, from 2005 to 2024. He emphasizes the personal nature of the talk, which is rich with anecdotes, highlighting how diverse perspectives, thoughtful API design, and open-source stewardship principles—like empathy, humility, and restraint—are crucial for evolving a framework used by millions of developers.

The Value of Diversity in Framework Design

Poutsma begins by noting his non-traditional computer science background, having studied Artificial Intelligence and Philosophy. He argues that a diverse team, not just in academic background but also in gender and nationality, leads to more robust and user-centric solutions. A team composed solely of computer scientists might create solutions that are too computer science-centric, alienating users who may not share that perspective. This diversity helps ensure the framework caters to a broader audience, including those who simply need to build applications without deep theoretical knowledge.

Evolution of Spring Web Controllers

  1. Early XML-based MVC: Poutsma reminisces about the initial Spring MVC, which relied heavily on XML configuration and required developers to extend base classes like MultiActionController. This approach was verbose, complex, and generally considered a “mess.”
  2. Annotation-driven MVC: Inspired by Java 5’s annotations and the “convention over configuration” trend popularized by Ruby on Rails, Poutsma spearheaded the @Controller and @RequestMapping annotations. This model moved configuration directly into classes, offering a more flexible and convenient way to define controllers, which contributed significantly to Spring’s popularity.
  3. Downsides of Annotations: Despite their success, annotations presented challenges: their “magical” nature made it hard for users to understand underlying behavior or override it. Extending the annotation model with custom behavior had a very steep learning curve.
  4. Functional MVC: To address the limitations of annotations, Spring introduced Functional MVC. This approach allows developers to write functions as handler methods, wired together using a DSL. This design explicitly reunites behavior and data, making the system more debuggable and easier for users to customize or override, resulting in fewer bug reports compared to the annotation model.

Anecdote: Why Spring MVC Uses Bubble Sort

Poutsma reveals that Spring MVC uses bubble sort within MimeTypeUtils for content negotiation. The challenge lies in determining the “most specific” media type from an Accept header. While standard sorting algorithms like Collections.sort require a total order, media types often have a partial order (e.g., text/html and text/plain are incomparable in specificity). Using a comparator on a partially ordered set can lead to IllegalArgumentException. Bubble sort, being stable and not requiring a total order, was adopted after a bug report revealed the issue, preventing exceptions and maintaining logical order.

Evolution of HTTP Clients

  1. RestTemplate: Introduced in Spring 3, RestTemplate followed the familiar Spring template pattern. However, it grew into a monolithic class with a vast number of overloaded methods, presenting an overwhelming array of choices to developers. This complexity limited its future extensibility, leading to its upcoming deprecation in Spring 7.
  2. WebClient and RestClient: Recognizing the issues with RestTemplate, Spring developed WebClient and subsequently RestClient. These clients employ a fluent API design, breaking down HTTP requests into a sequence of chained methods. Each method returns a specific subtype, guiding the user by only exposing relevant options (e.g., post() allows a body(), get() does not). This state-machine-like design creates a highly focused and less overwhelming API.

Anecdote: The Many URI Methods

Spring’s HTTP clients offer multiple ways to specify URIs (e.g., string with variables, string with repeated variables, or a java.net.URI object). This complexity stems from the need to handle URI encoding. While java.net.URI objects are inherently encoded, string inputs present a dilemma: should Spring encode them, risking double encoding if the user already did, or assume they are pre-encoded, risking errors? The solution was to provide separate methods, allowing users to explicitly signal whether a URI should be encoded by Spring (via string methods) or treated as pre-encoded (via java.net.URI). The key lesson learned: “Don’t do clever. Clever breaks down.”

Anecdote: Five Years to Fix a Mistake

Poutsma discusses a long-standing issue with the HttpMethod enum introduced in Spring 3. Initially, it was designed for a fixed set of HTTP methods (GET, POST, etc.). However, the HTTP specification allows for an open-ended set of methods (e.g., WebDAV’s LOCK, COPY). This oversight caused IllegalArgumentException for non-standard methods, necessitating a “nasty” getMethodValue() workaround that led to complex if/else logic for users. This situation illustrates Dan North’s concept of the “change event horizon”: for widely used frameworks like Spring, mistakes can persist for years due to the commitment to backward compatibility, which Poutsma sees as essential for respecting user time.

The Fix: The migration from Java EE to Jakarta EE in Spring 6 provided a unique opportunity. Requiring all users to recompile their code meant Spring could transition the HttpMethod enum to a class. Leveraging the fact that enums are special classes on the JVM, they recreated the enum’s behavior within a class, enabling support for arbitrary string methods while largely preserving the API. This change, while fundamental, was designed to be largely unnoticeable by most users, effectively fixing a five-year-old mistake.

Closing Thoughts: Open Source Stewardship

Poutsma concludes with personal insights into open-source stewardship:

  1. Empathy: Essential in both design and communication. Designers should anticipate common and edge cases, providing defaults and customization points. In bug reports, respond with understanding and sympathy, even when users are angry, as this builds strong community loyalty.
  2. Humility: Accept that initial designs might be flawed. Be open to feedback from early adopters and admit mistakes openly. “I was wrong. You’re right.” is a powerful phrase in issue trackers.
  3. Restraint: Embrace Josh Bloch’s advice: “When in doubt, leave it out.” Avoid implementing features if the requirements or optimal solution are unclear. This prevents premature, potentially incorrect implementations that might need to be fixed later. Also, avoid over-promising; show features when they are complete.

Share post

Stay In The Loop! Subscribe to Our Newsletter.

Get updates straight to your inbox. No spam, just useful content.

Recommended for You

Spring Then & Now: What’s Next? • Rod Johnson, Arjen Poutsma & Trisha Gee

Spring Then & Now: What’s Next? • Rod Johnson, Arjen Poutsma & Trisha Gee

A panel discussion with Spring Framework creator Rod Johnson and veteran Arjen Poutsma, moderated by Trisha Gee. They discuss the evolution of Spring, the future of reactive programming in the age of virtual threads, their new AI agent framework Embabel, and the essential AI skills modern Java developers need to acquire.

OpenAI’s Plan to Make ChatGPT the Everything App — Akshay Nathan, OpenAI

OpenAI’s Plan to Make ChatGPT the Everything App — Akshay Nathan, OpenAI

Akshay Nathan, head of Core Product Engineering at OpenAI, discusses the journey and rationale behind ChatGPT Work. He explains how Codex's unexpected adoption by non-developers led to a unified agent harness, blurring the lines between developer and knowledge worker tools. The conversation delves into model capabilities, the role of artifacts and interactive 'Sites' in replacing traditional documents, and how AI fosters a new era of 'T-shaped' generalists. Nathan emphasizes the shift in productivity bottlenecks to 'ideas and taste' and the importance of 'quality at-bats' over mere 'motion' in an AI-powered development landscape.