spring-boot-rest-client

Spring Boot Rest Client

License

License

Categories

Categories

Spring Boot Container Microservices Ant Build Tools CLI User Interface
GroupId

GroupId

io.github.polysantiago
ArtifactId

ArtifactId

spring-boot-rest-client
Last Version

Last Version

1.0.1
Release Date

Release Date

Type

Type

pom
Description

Description

spring-boot-rest-client
Spring Boot Rest Client
Project URL

Project URL

https://github.com/polysantiago/spring-boot-rest-client
Source Code Management

Source Code Management

https://github.com/polysantiago/spring-boot-rest-client

Download spring-boot-rest-client

How to add to project

<!-- https://jarcasting.com/artifacts/io.github.polysantiago/spring-boot-rest-client/ -->
<dependency>
    <groupId>io.github.polysantiago</groupId>
    <artifactId>spring-boot-rest-client</artifactId>
    <version>1.0.1</version>
    <type>pom</type>
</dependency>
// https://jarcasting.com/artifacts/io.github.polysantiago/spring-boot-rest-client/
implementation 'io.github.polysantiago:spring-boot-rest-client:1.0.1'
// https://jarcasting.com/artifacts/io.github.polysantiago/spring-boot-rest-client/
implementation ("io.github.polysantiago:spring-boot-rest-client:1.0.1")
'io.github.polysantiago:spring-boot-rest-client:pom:1.0.1'
<dependency org="io.github.polysantiago" name="spring-boot-rest-client" rev="1.0.1">
  <artifact name="spring-boot-rest-client" type="pom" />
</dependency>
@Grapes(
@Grab(group='io.github.polysantiago', module='spring-boot-rest-client', version='1.0.1')
)
libraryDependencies += "io.github.polysantiago" % "spring-boot-rest-client" % "1.0.1"
[io.github.polysantiago/spring-boot-rest-client "1.0.1"]

Dependencies

compile (8)

Group / Artifact Type Version
org.springframework.boot : spring-boot-autoconfigure jar
org.springframework.boot : spring-boot-starter-logging jar
org.springframework : spring-webmvc jar
org.springframework : spring-aop jar
org.aspectj : aspectjweaver jar
org.springframework.retry : spring-retry Optional jar
org.apache.commons : commons-lang3 jar 3.5
net.javacrumbs.future-converter : future-converter-spring-java8 jar 1.1.0

provided (1)

Group / Artifact Type Version
org.projectlombok : lombok jar

Project Modules

There are no modules declared in this project.

Spring Boot Rest Client

Build Status Maven Central GitHub issues GitHub 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 but it uses RestTemplate instead of Netflix's Feign and Spring MVC annotations.

As an additional feature, spring-boot-rest-client supports Spring Retry so that HTTP requests can be retried upon either specific HTTP statuses and/or defined Exceptions.

Usage

@EnableRestClients
@SpringBootApplication
public class FooApplication {
    
    public static void main(String... args) {
        SpringApplication.run(FooApplication.class, args);
    }
    
    @RestClient("foo")
    interface FooClient {
    
        @RequestMapping
        Foo getFoo();
    
    }
    
}
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

@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 header
  • consumes() - Value of the Content-Type 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:

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 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 as well as Spring's ListenableFuture.

@RestClient("foo")
interface FooClient {
    
    @RequestMapping("/{id}")
    ListenableFuture<String> foo(@PathVariable("id") String id, @RequestParam("query") String query);
    
    @RequestMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    CompletableFuture<Foo> 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:

interface FooBaseClient<T> {
    
    @GetMapping(value = "/{id}")
    T getParameterized(@PathVariable("id") String id);
    
}
@RestClient("foo")
interface FooClient extends FooBaseClient<Foo> {
    
}

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 as well as an HttpEntity.

@RestClient("foo")
interface FooClient {
    
    @GetMapping
    ResponseEntity<String> getEntity();
    
    @GetMapping
    HttpEntity<String> getHttpEntity();
    
}

JDK 8 Support

If you wrap your response type in Oracle's JDK 8 Optional, Spring Boot Rest Client will return an Optional.empty() upon a HTTP 404 NOT FOUND response code.

@RestClient("foo")
interface FooClient {
    
    @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    Optional<Foo> getOptional();
    
}

Please note that default methods in interfaces declaring @RestClient are currently not supported.

HATEOAS Support

Specially useful for HATEOAS, you can use the @PostForLocation annotation to indicate that a POST request should return the Location HTTP header as an URI.

@RestClient("foo")
interface FooClient {
    
    @PostForLocation("/postForLocation")
    URI postForLocation(String body);
    
}

Additionally, by including Spring HATEOAS as a dependency, you can use Spring HATEOAS resource support:

public class FooResource extends ResourceSupport {
    
}
@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<Foo> getFooWrapped(@PathVariable("id") String id);
    
    @GetMapping(value = "/foos", produces = MediaTypes.HAL_JSON_VALUE)
    Resources<FooResource> getFoos();
    
    @GetMapping(value = "/foos", produces = MediaTypes.HAL_JSON_VALUE)
    PagedResources<FooResource> 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:

@RestClient(
    value = "foo", 
    retryOn = {HttpStatus.SERVICE_UNAVAILABLE, HttpStatus.BAD_GATEWAY}, 
    retryOnException = SocketTimeoutException.class)
interface FooClient {
    
    @RestClient("/foos")
    List<Foo> getFooList();
    
}

Furthermore, global retry settings can be configured by adding values to application.yml. Below, the default values are shown:

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 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
  • 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

TODO

  • Add option to disable retry on either clients or specific methods
  • Support @Recover method as specified in Spring Retry when retries are exhausted

Versions

Version
1.0.1
1.0.0