val result = restClient.get()
.uri("https://petclinic.example.com/pets/{id}", id)
.accept(MediaType.APPLICATION_JSON)
.exchange { request, response -> (1)
if (response.getStatusCode().is4xxClientError()) { (2)
throw MyCustomRuntimeException(response.getStatusCode(), response.getHeaders()) (2)
} else {
val pet: Pet = convertResponse(response) (3)
See the supported HTTP message converters in the dedicated section.
To serialize only a subset of the object properties, you can specify a Jackson JSON View, as the following example shows:
MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23"));
value.setSerializationView(User.WithoutPasswordView.class);
ResponseEntity<Void> response = restClient.post() // or RestTemplate.postForEntity
.contentType(APPLICATION_JSON)
.body(value)
.retrieve()
.toBodilessEntity();
To send multipart data, you need to provide a MultiValueMap<String, Object>
whose values may be an Object
for part content, a Resource
for a file part, or an HttpEntity
for part content with headers.
For example:
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("fieldPart", "fieldValue");
parts.add("filePart", new FileSystemResource("...logo.png"));
parts.add("jsonPart", new Person("Jason"));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
parts.add("xmlPart", new HttpEntity<>(myBean, headers));
// send using RestClient.post or RestTemplate.postForEntity
In most cases, you do not have to specify the Content-Type
for each part.
The content type is determined automatically based on the HttpMessageConverter
chosen to serialize it or, in the case of a Resource
, based on the file extension.
If necessary, you can explicitly provide the MediaType
with an HttpEntity
wrapper.
Once the MultiValueMap
is ready, you can use it as the body of a POST
request, using RestClient.post().body(parts)
(or RestTemplate.postForObject
).
If the MultiValueMap
contains at least one non-String
value, the Content-Type
is set to multipart/form-data
by the FormHttpMessageConverter
.
If the MultiValueMap
has String
values, the Content-Type
defaults to application/x-www-form-urlencoded
.
If necessary the Content-Type
may also be set explicitly.
To execute the HTTP request, RestClient
uses a client HTTP library.
These libraries are adapted via the ClientRequestFactory
interface.
Various implementations are available:
If no request factory is specified when the RestClient
was built, it will use the Apache or Jetty HttpClient
if they are available on the classpath.
Otherwise, if the java.net.http
module is loaded, it will use Java’s HttpClient
.
Finally, it will resort to the simple default.
Note that the SimpleClientHttpRequestFactory
may raise an exception when accessing the status of a response that represents an error (for example, 401).
If this is an issue, use any of the alternative request factories.
WebClient
is a non-blocking, reactive client to perform HTTP requests. It was
introduced in 5.0 and offers an alternative to the RestTemplate
, with support for
synchronous, asynchronous, and streaming scenarios.
WebClient
supports the following:
The RestTemplate
provides a high-level API over HTTP client libraries in the form of a classic Spring Template class.
It exposes the following groups of overloaded methods:
getForEntity
Retrieves a ResponseEntity
(that is, status, headers, and body) by using GET.
headForHeaders
Retrieves all headers for a resource by using HEAD.
postForLocation
Creates a new resource by using POST and returns the Location
header from the response.
postForObject
Creates a new resource by using POST and returns the representation from the response.
postForEntity
Creates a new resource by using POST and returns the representation from the response.
Creates or updates a resource by using PUT.
patchForObject
Updates a resource by using PATCH and returns the representation from the response.
Note that the JDK HttpURLConnection
does not support PATCH
, but Apache HttpComponents and others do.
delete
Deletes the resources at the specified URI by using DELETE.
optionsForAllow
Retrieves allowed HTTP methods for a resource by using ALLOW.
exchange
More generalized (and less opinionated) version of the preceding methods that provides extra flexibility when needed.
It accepts a RequestEntity
(including HTTP method, URL, headers, and body as input) and returns a ResponseEntity
.
These methods allow the use of ParameterizedTypeReference
instead of Class
to specify
a response type with generics.
execute
The most generalized way to perform a request, with full control over request
preparation and response extraction through callback interfaces.
RestTemplate
uses the same HTTP library abstraction as RestClient
.
By default, it uses the SimpleClientHttpRequestFactory
, but this can be changed via the constructor.
See Client Request Factories.
RestTemplate
can be instrumented for observability, in order to produce metrics and traces.
See the RestTemplate Observability support section.
The following table shows RestClient
equivalents for RestTemplate
methods.
It can be used to migrate from the latter to the former.
Table 2. RestClient equivalents for RestTemplate methods
exchange(String, HttpMethod, HttpEntity, Class, Object…)
method(HttpMethod)
.uri(String, Object…)
.headers(Consumer<HttpHeaders>)
.body(Object)
.retrieve()
.toEntity(Class)
]
exchange(String, HttpMethod, HttpEntity, Class, Map)
method(HttpMethod)
.uri(String, Map)
.headers(Consumer<HttpHeaders>)
.body(Object)
.retrieve()
.toEntity(Class)
exchange(URI, HttpMethod, HttpEntity, Class)
method(HttpMethod)
.uri(URI)
.headers(Consumer<HttpHeaders>)
.body(Object)
.retrieve()
.toEntity(Class)
exchange(String, HttpMethod, HttpEntity, ParameterizedTypeReference, Object…)
method(HttpMethod)
.uri(String, Object…)
.headers(Consumer<HttpHeaders>)
.body(Object)
.retrieve()
.toEntity(ParameterizedTypeReference)
exchange(String, HttpMethod, HttpEntity, ParameterizedTypeReference, Map)
method(HttpMethod)
.uri(String, Map)
.headers(Consumer<HttpHeaders>)
.body(Object)
.retrieve()
.toEntity(ParameterizedTypeReference)
exchange(URI, HttpMethod, HttpEntity, ParameterizedTypeReference)
method(HttpMethod)
.uri(URI)
.headers(Consumer<HttpHeaders>)
.body(Object)
.retrieve()
.toEntity(ParameterizedTypeReference)
exchange(RequestEntity, Class)
method(HttpMethod)
.uri(URI)
.headers(Consumer<HttpHeaders>)
.body(Object)
.retrieve()
.toEntity(Class)
exchange(RequestEntity, ParameterizedTypeReference)
method(HttpMethod)
.uri(URI)
.headers(Consumer<HttpHeaders>)
.body(Object)
.retrieve()
.toEntity(ParameterizedTypeReference)
execute(String, HttpMethod, RequestCallback, ResponseExtractor, Object…)
method(HttpMethod)
.uri(String, Object…)
.exchange(ExchangeFunction)
execute(String, HttpMethod, RequestCallback, ResponseExtractor, Map)
method(HttpMethod)
.uri(String, Map)
.exchange(ExchangeFunction)
execute(URI, HttpMethod, RequestCallback, ResponseExtractor)
method(HttpMethod)
.uri(URI)
.exchange(ExchangeFunction)
The Spring Framework lets you define an HTTP service as a Java interface with
@HttpExchange
methods. You can pass such an interface to HttpServiceProxyFactory
to create a proxy which performs requests through an HTTP client such as RestClient
or WebClient
. You can also implement the interface from an @Controller
for server
request handling.
Start by creating the interface with @HttpExchange
methods:
interface RepositoryService {
@GetExchange("/repos/{owner}/{repo}")
Repository getRepository(@PathVariable String owner, @PathVariable String repo);
// more HTTP exchange methods...
Now you can create a proxy that performs requests when methods are called.
For RestClient
:
RestClient restClient = RestClient.builder().baseUrl("https://api.github.com/").build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
RepositoryService service = factory.createClient(RepositoryService.class);
For WebClient
:
WebClient webClient = WebClient.builder().baseUrl("https://api.github.com/").build();
WebClientAdapter adapter = WebClientAdapter.create(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
RepositoryService service = factory.createClient(RepositoryService.class);
For RestTemplate
:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory("https://api.github.com/"));
RestTemplateAdapter adapter = RestTemplateAdapter.create(restTemplate);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
RepositoryService service = factory.createClient(RepositoryService.class);
@HttpExchange
is supported at the type level where it applies to all methods:
@HttpExchange(url = "/repos/{owner}/{repo}", accept = "application/vnd.github.v3+json")
interface RepositoryService {
@GetExchange
Repository getRepository(@PathVariable String owner, @PathVariable String repo);
@PatchExchange(contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
void updateRepository(@PathVariable String owner, @PathVariable String repo,
@RequestParam String name, @RequestParam String description, @RequestParam String homepage);
Annotated, HTTP exchange methods support flexible method signatures with the following
method parameters:
UriBuilderFactory
Provide a UriBuilderFactory
to expand the URI template and URI variables with.
In effect, replaces the UriBuilderFactory
(and its base URL) of the underlying client.
HttpMethod
Dynamically set the HTTP method for the request, overriding the annotation’s method
attribute
@RequestHeader
Add a request header or multiple headers. The argument may be a Map<String, ?>
or
MultiValueMap<String, ?>
with multiple headers, a Collection<?>
of values, or an
individual value. Type conversion is supported for non-String values. This overrides
the annotation’s headers
attribute.
@PathVariable
Add a variable for expand a placeholder in the request URL. The argument may be a
Map<String, ?>
with multiple variables, or an individual value. Type conversion
is supported for non-String values.
@RequestAttribute
Provide an Object
to add as a request attribute. Only supported by RestClient
and WebClient
.
@RequestBody
Provide the body of the request either as an Object to be serialized, or a
Reactive Streams Publisher
such as Mono
, Flux
, or any other async type supported
through the configured ReactiveAdapterRegistry
.
@RequestParam
Add a request parameter or multiple parameters. The argument may be a Map<String, ?>
or MultiValueMap<String, ?>
with multiple parameters, a Collection<?>
of values, or
an individual value. Type conversion is supported for non-String values.
When "content-type"
is set to "application/x-www-form-urlencoded"
, request
parameters are encoded in the request body. Otherwise, they are added as URL query
parameters.
@RequestPart
Add a request part, which may be a String (form field), Resource
(file part),
Object (entity to be encoded, for example, as JSON), HttpEntity
(part content and headers),
a Spring Part
, or Reactive Streams Publisher
of any of the above.
MultipartFile
Add a request part from a MultipartFile
, typically used in a Spring MVC controller
where it represents an uploaded file.
@CookieValue
Add a cookie or multiple cookies. The argument may be a Map<String, ?>
or
MultiValueMap<String, ?>
with multiple cookies, a Collection<?>
of values, or an
individual value. Type conversion is supported for non-String values.
Method parameters cannot be null
unless the required
attribute (where available on a
parameter annotation) is set to false
, or the parameter is marked optional as determined by
MethodParameter#isOptional
.
The supported return values depend on the underlying client.
Clients adapted to HttpExchangeAdapter
such as RestClient
and RestTemplate
support synchronous return values:
ResponseEntity<Void>
Perform the given request and return a ResponseEntity
with the status and headers.
ResponseEntity<T>
Perform the given request, decode the response content to the declared return type, and
return a ResponseEntity
with the status, headers, and the decoded body.
Clients adapted to ReactorHttpExchangeAdapter
such as WebClient
, support all of above
as well as reactive variants. The table below shows Reactor types, but you can also use
other reactive types that are supported through the ReactiveAdapterRegistry
:
Mono<HttpHeaders>
Perform the given request, release the response content, if any, and return the
response headers.
Mono<T>
Perform the given request and decode the response content to the declared return type.
Flux<T>
Perform the given request and decode the response content to a stream of the declared
element type.
Mono<ResponseEntity<Void>>
Perform the given request, and release the response content, if any, and return a
ResponseEntity
with the status and headers.
Mono<ResponseEntity<T>>
Perform the given request, decode the response content to the declared return type, and
return a ResponseEntity
with the status, headers, and the decoded body.
Mono<ResponseEntity<Flux<T>>
Perform the given request, decode the response content to a stream of the declared
element type, and return a ResponseEntity
with the status, headers, and the decoded
response body stream.
By default, the timeout for synchronous return values with ReactorHttpExchangeAdapter
depends on how the underlying HTTP client is configured. You can set a blockTimeout
value on the adapter level as well, but we recommend relying on timeout settings of the
underlying HTTP client, which operates at a lower level and provides more control.
To customize error response handling, you need to configure the underlying HTTP client.
For RestClient
:
By default, RestClient
raises RestClientException
for 4xx and 5xx HTTP status codes.
To customize this, register a response status handler that applies to all responses
performed through the client:
RestClient restClient = RestClient.builder()
.defaultStatusHandler(HttpStatusCode::isError, (request, response) -> ...)
.build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
For more details and options, such as suppressing error status codes, see the Javadoc of
defaultStatusHandler
in RestClient.Builder
.
For WebClient
:
By default, WebClient
raises WebClientResponseException
for 4xx and 5xx HTTP status codes.
To customize this, register a response status handler that applies to all responses
performed through the client:
WebClient webClient = WebClient.builder()
.defaultStatusHandler(HttpStatusCode::isError, resp -> ...)
.build();
WebClientAdapter adapter = WebClientAdapter.create(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(adapter).build();
For more details and options, such as suppressing error status codes, see the Javadoc of
defaultStatusHandler
in WebClient.Builder
.
For RestTemplate
:
By default, RestTemplate
raises RestClientException
for 4xx and 5xx HTTP status codes.
To customize this, register an error handler that applies to all responses
performed through the client:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(myErrorHandler);
RestTemplateAdapter adapter = RestTemplateAdapter.create(restTemplate);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
For more details and options, see the Javadoc of setErrorHandler
in RestTemplate
and
the ResponseErrorHandler
hierarchy.
1. HttpEntity
headers and body have to be supplied to the RestClient
via headers(Consumer<HttpHeaders>)
and body(Object)
.
2. RequestEntity
method, URI, headers and body have to be supplied to the RestClient
via method(HttpMethod)
, uri(URI)
, headers(Consumer<HttpHeaders>)
and body(Object)
.
Integration
JMS (Java Message Service)
Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra™, and Apache Geode™ are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java™, Java™ SE, Java™ EE, and OpenJDK™ are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners.