Spring Update #4 – Introducing "Declarative HTTP Clients" & support for the "Problem Details for HTTP APIs"
In late 2022, the Spring teams released versions 6 and 3 of the Spring Framework and Spring Boot, respectively
In this edition of my 4 part blog series, which highlights the most important updates from the new releases, I’ll finish the series with the last two significant updates I wanted to share with you: The introduction of “Declarative HTTP Clients” & support for the “Problem Details for HTTP APIs” specification
Check out my previous blog posts in this series: “New Baselines: Java 17 and Jakarta EE,” “AOT and Native Compilation” & “We Shall See: Micrometer-based Observability” if you haven’t already.
To begin this article let’s explore the introduction of Declarative HTTP clients.
Declarative HTTP Clients
Spring 6 provides a new feature to generate HTTP clients based on interfaces and annotations. This is similar to what OpenFeign does as well, but is now supported directly within the framework.
Here’s an example from the Spring documentation. You start by defining an interface with one or more methods that you annotate with a new exchange annotation:
interface RepositoryService {
@GetExchange("/repos/{owner}/{repo}")
Repository getRepository(@PathVariable String owner, @PathVariable String repo)
// more HTTP exchange methods...
}
This shows how, next to the new @GetExchange, existing Spring Web annotations like @PathVariable are used.
You then ask Spring to generate an implementation for your interface:
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
RepositoryService service = factory.createClient(RepositoryService.class);
Note that this uses the reactive WebClient as the underlying client: however, this does not force you to use reactive types like Mono and Flux in your declarations.
The Spring team has also started to work on a version of the WebClient that’s compatible with Loom, as an alternative to the current reactive implementation: that would finally provide a proper successor to the RestTemplate for applications that aren’t using Reactor and Webflux.
For more information, check out the reference documentation.
Houston, We Have A Problem
Spring Boot has always provided support for generating error responses in web applications for when uncaught exceptions are thrown from controllers. The format of these errors is quite limited, however, and more importantly Boot-specific.
Spring 6 has added support for the “Problem Details for HTTP APIs” specification, RFC 7807. This allows error to be described in a default JSON format containing both predefined as well as custom fields. The content type of such an error response is “application/problem+json”.
Here’s an example of such an error response:
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": ["/account/12345", "/account/67890"]
}
Note how the “type” field contains a URI. Although it’s not a hard requirement, it is expected that this is a URL that points to a web page containing error documentation. “balance” and “accounts” are custom fields.
Personally I haven’t run into public APIs that use this new standard yet: this new integration might change that in the foreseeable future.
The support is in place for both Spring-MVC and Webflux. Check the documentation for more information on how to enable this functionality.
A little tip on the side: if you’re interested in more options for web error handling, check out the error-handling-spring-boot-starter library written by Wim Deblauwe. With version 4.0.0 that already provides support for Spring Boot 3 as well!
What Else?
In this blog series, we’ve covered the major changes, but a lot of smaller issues have been addressed as well: you can learn more about those in the release notes, blog posts and other resources.
For more information on how to upgrade to Boot 3 you should study the migration guide. For example, you might need to adapt your own auto-configuration setup if that still uses the spring.factories file, or you may need to upgrade your Apache HTTP client to a newer version.
New versions of frameworks like Spring Security come with their own set of changes: for example, the antMatchers and mvcMatchers methods have been replaced with a requestMatchers method.
To assist you in the upgrade, there’s also a dedicated tool available called the Spring Boot Migrator, based on OpenRewrite
This wraps up the series. I hope you learned something new. If you want to discuss this article or anything else Spring related make sure to drop me a message on twitter @joriskuipers.