Skip to content

Commit

Permalink
Add support for RestClient API (#75)
Browse files Browse the repository at this point in the history
Fixes #74.
  • Loading branch information
jpraet authored Jul 1, 2024
1 parent 4d6b5a0 commit 51e8ba6
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

public enum Client {

REST_TEMPLATE, WEB_CLIENT
REST_TEMPLATE, WEB_CLIENT, REST_CLIENT

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;

Expand All @@ -33,13 +34,20 @@ public class FrontendController implements ControllerInterface {

private final WebClient.Builder webClientBuilder;

private final RestClient.Builder restClientBuilder;

private RestTemplate restTemplate;

private WebClient webClient;

public FrontendController(RestTemplateBuilder restTemplateBuilder, WebClient.Builder webClientBuilder) {
private RestClient restClient;

public FrontendController(RestTemplateBuilder restTemplateBuilder,
WebClient.Builder webClientBuilder,
RestClient.Builder restClientBuilder) {
this.restTemplateBuilder = restTemplateBuilder;
this.webClientBuilder = webClientBuilder;
this.restClientBuilder = restClientBuilder;
}

@EventListener
Expand All @@ -48,7 +56,11 @@ public void onApplicationEvent(ServletWebServerInitializedEvent event) {
.rootUri("http://localhost:" + event.getWebServer().getPort() + "/spring/backend")
.build();
this.webClient = webClientBuilder
.baseUrl("http://localhost:" + event.getWebServer().getPort() + "/spring/backend").build();
.baseUrl("http://localhost:" + event.getWebServer().getPort() + "/spring/backend")
.build();
this.restClient = restClientBuilder
.baseUrl("http://localhost:" + event.getWebServer().getPort() + "/spring/backend")
.build();
}

@GetMapping("/badRequest")
Expand Down Expand Up @@ -90,6 +102,8 @@ public void badRequestFromBackend(@RequestParam("client") Client client) {
restTemplate.getForObject("/badRequest", String.class);
} else if (client == Client.WEB_CLIENT) {
webClient.get().uri("/badRequest").retrieve().toEntity(String.class).block();
} else if (client == Client.REST_CLIENT) {
restClient.get().uri("/badRequest").retrieve().toEntity(String.class);
}
throw new IllegalStateException(ILLEGAL_STATE_MESSAGE_PREFIX + client);
} catch (BadRequestProblem e) {
Expand All @@ -105,6 +119,8 @@ public void customFromBackend(@RequestParam("client") Client client) {
restTemplate.getForObject("/custom", String.class);
} else if (client == Client.WEB_CLIENT) {
webClient.get().uri("/custom").retrieve().toEntity(String.class).block();
} else if (client == Client.REST_CLIENT) {
restClient.get().uri("/custom").retrieve().toEntity(String.class);
}
throw new IllegalStateException(ILLEGAL_STATE_MESSAGE_PREFIX + client);
} catch (CustomProblem e) {
Expand All @@ -120,6 +136,8 @@ public void unmappedFromBackend(@RequestParam("client") Client client) {
restTemplate.getForObject("/unmapped", String.class);
} else if (client == Client.WEB_CLIENT) {
webClient.get().uri("/unmapped").retrieve().toEntity(String.class).block();
} else if (client == Client.REST_CLIENT) {
restClient.get().uri("/unmapped").retrieve().toEntity(String.class);
}
throw new IllegalStateException(ILLEGAL_STATE_MESSAGE_PREFIX + client);
} catch (DefaultProblem e) {
Expand Down
5 changes: 5 additions & 0 deletions belgif-rest-problem-spring-boot-3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
<artifactId>spring-webmvc</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.github.belgif.rest.problem.spring;

import org.springframework.boot.web.client.RestClientCustomizer;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

/**
* RestClientCustomizer that registers the {@link ProblemResponseErrorHandler}.
*
* @see ProblemResponseErrorHandler
*/
@Component
public class ProblemRestClientCustomizer implements RestClientCustomizer {

private final ProblemResponseErrorHandler errorHandler;

public ProblemRestClientCustomizer(ProblemResponseErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}

@Override
public void customize(RestClient.Builder restClientBuilder) {
restClientBuilder.defaultStatusHandler(errorHandler);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.github.belgif.rest.problem.spring;

import static org.assertj.core.api.Assertions.*;

import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.RestClient;

import com.fasterxml.jackson.databind.ObjectMapper;

class ProblemRestClientCustomizerTest {

@Test
void customize() {
ProblemResponseErrorHandler handler = new ProblemResponseErrorHandler(new ObjectMapper());
ProblemRestClientCustomizer customizer = new ProblemRestClientCustomizer(handler);
RestClient.Builder builder = RestClient.builder();
customizer.customize(builder);

List<?> statusHandlers = (List<?>) ReflectionTestUtils.getField(builder, "statusHandlers");
assertThat(statusHandlers).hasSize(1);
}

}
4 changes: 3 additions & 1 deletion src/main/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ To benefit from Spring Boot 2.x or 3.x specific features, replace dependencies t
*belgif-rest-problem-spring-boot-3:*

* Map NoResourceFoundException to 404 `urn:problem-type:belgif:resourceNotFound`
* Added support for https://docs.spring.io/spring-framework/reference/integration/rest-clients.html#rest-restclient[RestClient] API

=== Version 0.4

Expand Down Expand Up @@ -348,7 +349,7 @@ io.github.belgif.rest.problem.scan-additional-problem-packages=com.acme.custom
* *BeanValidationExceptionsHandler:* an exception handler for RestControllers that converts bean validation related exceptions to HTTP 400 BadRequestProblem.
* *RoutingExceptionsHandler:* an exception handler for RestControllers that converts routing related validation exceptions to HTTP 400 BadRequestProblem.
* *ProblemResponseErrorHandler:* a RestTemplate error handler that converts problem responses to Problem exceptions.
* *ProblemRestTemplateCustomizer:* a RestTemplateCustomizer that registers the ProblemResponseErrorHandler
* *ProblemRestTemplateCustomizer:* a RestTemplateCustomizer that registers the ProblemResponseErrorHandler.
* *ProblemWebClientCustomizer:* a WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions.
This handles integration with the https://docs.spring.io/spring-framework/reference/web/webflux-webclient.html[Reactive WebClient].

Expand All @@ -365,6 +366,7 @@ Rather than depending on <<belgif-rest-problem-spring>> directly, Spring Boot 2.
Rather than depending on <<belgif-rest-problem-spring>> directly, Spring Boot 3.x users are recommended to depend on `belgif-rest-problem-spring-boot-3`, which adds some Spring Boot 3.x specific integrations:

* *NoResourceFoundExceptionHandler:* an exception handler for RestControllers that converts NoResourceFoundException to HTTP 404 ResourceNotFoundProblem.
* *ProblemRestClientCustomizer:* a RestClientCustomizer that registers the ProblemResponseErrorHandler.

[[code-generators]]
== Code generators
Expand Down

0 comments on commit 51e8ba6

Please sign in to comment.