Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/polysantiago/spring-boot-rest-client
A Rest Client for Spring Boot
https://github.com/polysantiago/spring-boot-rest-client
annotations bean hateoas java-8 microservices rest-microservice retries spring-boot spring-framework spring-mvc spring-rest
Last synced: about 1 month ago
JSON representation
A Rest Client for Spring Boot
- Host: GitHub
- URL: https://github.com/polysantiago/spring-boot-rest-client
- Owner: polysantiago
- License: mit
- Created: 2017-03-30T18:52:23.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2019-08-20T09:28:17.000Z (about 5 years ago)
- Last Synced: 2024-09-29T00:05:39.419Z (about 2 months ago)
- Topics: annotations, bean, hateoas, java-8, microservices, rest-microservice, retries, spring-boot, spring-framework, spring-mvc, spring-rest
- Language: Java
- Size: 309 KB
- Stars: 19
- Watchers: 4
- Forks: 10
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Spring Boot Rest Client
=======[![Build Status](https://travis-ci.org/polysantiago/spring-boot-rest-client.svg?branch=master)](https://travis-ci.org/polysantiago/spring-boot-rest-client)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.polysantiago/spring-boot-rest-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.github.polysantiago/spring-boot-rest-client)
[![GitHub issues](https://img.shields.io/github/issues/polysantiago/spring-boot-rest-client.svg)](https://github.com/polysantiago/spring-boot-rest-client/issues)
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/polysantiago/spring-boot-rest-client/master/LICENSE)This library was born as an effort to avoid boilerplate code and making use of Spring Boot's auto-configuration features.
It is based on [Spring Cloud Feign](http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign) but it
uses [RestTemplate](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html)
instead of Netflix's Feign and [Spring MVC annotations](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html).As an additional feature, **spring-boot-rest-client** supports [Spring Retry](https://github.com/spring-projects/spring-retry)
so that HTTP requests can be retried upon either specific HTTP statuses and/or defined Exceptions.Usage
-----```java
@EnableRestClients
@SpringBootApplication
public class FooApplication {
public static void main(String... args) {
SpringApplication.run(FooApplication.class, args);
}
@RestClient("foo")
interface FooClient {
@RequestMapping
Foo getFoo();
}
}
``````yaml
spring:
rest:
client:
services:
foo: http://foo.bar.se
```
You can later use `@Autowired` (or constructor injection) and just call `fooClient.getFoo()` which will
make an `HTTP GET` call to `http://foo.bar.se````java
@Component
public class RestClientConsumer {
private final FooClient fooClient;
RestClientConsumer(FooClient fooClient) {
this.fooClient = fooClient;
}
public Foo getFoo() {
return fooClient.getFoo();
}
}
```Structure
-----
`@RequestMapping` values have the following correspondence to the resulting HTTP call:
* `value()` - Path appended to the host
* `method()` - The HTTP method (GET is the default)
* `produces()` - Value of the [Accept](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1) header
* `consumes()` - Value of the [Content-Type](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) header
* `headers()` - `String[]` of key-value pairs of headers separated by ':'All HTTP REST methods are supported (GET, POST, PUT, PATCH and DELETE) as well as the following annotations on parameters:
* [RequestParam](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestParam.html)
* [PathVariable](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/PathVariable.html)
* [RequestHeader](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestHeader.html)
* [RequestBody](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestBody.html)
A method parameter with no annotation is expected to be the request body (payload) of the request
if `@RequestBody` is not specified.In addition to `@RequestMapping`, composed variants introduced in Spring MVC 4.3 can also be used.
Check [this](https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-composed)
for more details.Async
-----
Spring Boot Rest Template can be also be configured to be used for asynchronous REST calls for which it will instead use
an `AsyncRestTemplate` bean. It supports both Oracle's [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)
as well as Spring's [ListenableFuture](http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/concurrent/ListenableFuture.html).```java
@RestClient("foo")
interface FooClient {
@RequestMapping("/{id}")
ListenableFuture foo(@PathVariable("id") String id, @RequestParam("query") String query);
@RequestMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
CompletableFuture getFoo(@PathVariable("id") String id);
}
```Please note that retry functionality is currently not supported for asynchronous requests.
Generics
-----
Generic declarations are supported as long as the "implementing" interface contains a concrete class.Working example:
```java
interface FooBaseClient {
@GetMapping(value = "/{id}")
T getParameterized(@PathVariable("id") String id);
}
```
```java
@RestClient("foo")
interface FooClient extends FooBaseClient {
}
```HTTP Entities
-----
If for some reason you do not wish to have the body extracted from your response, you can wrap your response type in
either a [ResponseEntity](http://docs.spring.io/autorepo/docs/spring/current/javadoc-api/org/springframework/http/ResponseEntity.html)
as well as an [HttpEntity](http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/HttpEntity.html).```java
@RestClient("foo")
interface FooClient {
@GetMapping
ResponseEntity getEntity();
@GetMapping
HttpEntity getHttpEntity();
}
```JDK 8 Support
-----
If you wrap your response type in Oracle's JDK 8 [Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html),
Spring Boot Rest Client will return an `Optional.empty()` upon a `HTTP 404 NOT FOUND` response code.```java
@RestClient("foo")
interface FooClient {
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
Optional getOptional();
}
```Please note that **default** methods in interfaces declaring `@RestClient` are currently not supported.
HATEOAS Support
-----Specially useful for [HATEOAS](https://en.wikipedia.org/wiki/HATEOAS), you can use the `@PostForLocation` annotation to
indicate that a POST request should return the `Location` HTTP header as an `URI`.```java
@RestClient("foo")
interface FooClient {
@PostForLocation("/postForLocation")
URI postForLocation(String body);
}
```Additionally, by including [Spring HATEOAS](https://github.com/spring-projects/spring-hateoas) as a dependency, you can
use Spring HATEOAS resource support:```java
public class FooResource extends ResourceSupport {
}
```
```java
@RestClient("foo")
interface FooClient {
@GetMapping(value = "/foo/{id}", produces = MediaTypes.HAL_JSON_VALUE)
FooResource getFoo(@PathVariable("id") String id);
@GetMapping(value = "/foo/{id}", produces = MediaTypes.HAL_JSON_VALUE)
Resource getFooWrapped(@PathVariable("id") String id);
@GetMapping(value = "/foos", produces = MediaTypes.HAL_JSON_VALUE)
Resources getFoos();
@GetMapping(value = "/foos", produces = MediaTypes.HAL_JSON_VALUE)
PagedResources getPagedFoos();
}
```
Retry
-----The rest client library can be used with Spring Retry. Just by adding the `org.springframework.retry:spring-retry`
library as a dependency and `@EnableRetry` in your configuration, the retry functionality will be enabled.
By default, calls are retried on `HTTP 503 SERVICE UNAVAILABLE` and `IOException` but you can configure your own:```java
@RestClient(
value = "foo",
retryOn = {HttpStatus.SERVICE_UNAVAILABLE, HttpStatus.BAD_GATEWAY},
retryOnException = SocketTimeoutException.class)
interface FooClient {
@RestClient("/foos")
List getFooList();
}
```
Furthermore, global retry settings can be configured by adding values to `application.yml`. Below, the default values
are shown:```yaml
spring:
rest:
client:
services:
foo: http://foo.bar.se
retry:
max-attempts: 3
back-off:
delay: 1000
max-delay: 0
multiplier: 0.0
random: false
```Refer to [Spring Retry](https://github.com/spring-projects/spring-retry) for more information about what the values refer to.
Miscellaneous
-------------* The library will create a `RestTemplate` and a `AsyncRestTemplate` Spring beans if not already present using a
[RestTemplateBuilder](http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/client/RestTemplateBuilder.html)
* The library is non-intrusive. That means that if you want the spring-retry functionality you'll need to include it and
all of its dependencies
* `@RestClient` also accepts an optional `url()` parameter which can be either a hardcoded value
or a [SpEL expression](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/expressions.html)TODO
----* Add option to disable retry on either clients or specific methods
* Support `@Recover` method as specified in Spring Retry when retries are exhausted