Skip to content

Commit

Permalink
feat : optimizing REST client configurations using RestClientCustomiz…
Browse files Browse the repository at this point in the history
…er (#1178)

* feat : set RestClient using RestClientCustomizer

* create restclient bean

* feat : externalize configuration URL

* enchance WebMVC Config

* fix : issue with configuring WebMVC

* fix : issue with reading configurationProperties

* adds proxy beans

* ReOrder Beans
  • Loading branch information
rajadilipkolli authored Apr 7, 2024
1 parent 7d94c44 commit eb3b605
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
import org.springframework.boot.web.client.RestClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
Expand Down Expand Up @@ -69,12 +70,11 @@ public CloseableHttpClient httpClient() {
}

@Bean
HttpServiceProxyFactory httpServiceProxyFactory(
RestClient.Builder builder,
ObservationRegistry observationRegistry,
CloseableHttpClient httpClient) {
RestClient restClient =
builder.defaultHeaders(
RestClientCustomizer restClientCustomizer(
ObservationRegistry observationRegistry, CloseableHttpClient httpClient) {
return restClientBuilder ->
restClientBuilder
.defaultHeaders(
httpHeaders -> {
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(List.of(MediaType.APPLICATION_JSON));
Expand All @@ -90,9 +90,12 @@ HttpServiceProxyFactory httpServiceProxyFactory(
log.info("HTTP Headers: {}", request.getHeaders());

return execution.execute(request, body);
})
.build();
RestClientAdapter webClientAdapter = RestClientAdapter.create(restClient);
});
}

@Bean
HttpServiceProxyFactory httpServiceProxyFactory(RestClient.Builder restClientBuilder) {
RestClientAdapter webClientAdapter = RestClientAdapter.create(restClientBuilder.build());
return HttpServiceProxyFactory.builderFor(webClientAdapter).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@Configuration(proxyBeanMethods = false)
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {
private final ApplicationProperties properties;

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping(properties.getCors().getPathPattern())
.allowedMethods(properties.getCors().getAllowedMethods())
.allowedHeaders(properties.getCors().getAllowedHeaders())
.allowedOriginPatterns(properties.getCors().getAllowedOriginPatterns())
.allowCredentials(properties.getCors().isAllowCredentials());
public void addCorsMappings(@NonNull CorsRegistry registry) {
ApplicationProperties.Cors propertiesCors = properties.getCors();
registry.addMapping(propertiesCors.getPathPattern())
.allowedMethods(propertiesCors.getAllowedMethods())
.allowedHeaders(propertiesCors.getAllowedHeaders())
.allowedOriginPatterns(propertiesCors.getAllowedOriginPatterns())
.allowCredentials(propertiesCors.isAllowCredentials());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package com.example.rest.template.config;

import static com.example.rest.template.utils.AppConstants.*;
import static com.example.rest.template.utils.AppConstants.CONNECTION_TIMEOUT;
import static com.example.rest.template.utils.AppConstants.DEFAULT_KEEP_ALIVE_TIME;
import static com.example.rest.template.utils.AppConstants.IDLE_CONNECTION_WAIT_TIME;
import static com.example.rest.template.utils.AppConstants.MAX_LOCALHOST_CONNECTIONS;
import static com.example.rest.template.utils.AppConstants.MAX_ROUTE_CONNECTIONS;
import static com.example.rest.template.utils.AppConstants.MAX_TOTAL_CONNECTIONS;
import static com.example.rest.template.utils.AppConstants.REQUEST_TIMEOUT;
import static com.example.rest.template.utils.AppConstants.SOCKET_TIMEOUT;

import java.time.Duration;
import java.util.Iterator;
Expand Down Expand Up @@ -49,7 +56,7 @@ PoolingHttpClientConnectionManager poolingConnectionManager() {
new PoolingHttpClientConnectionManager(registry);

poolingConnectionManager.setDefaultSocketConfig(
SocketConfig.custom().setSoTimeout(Timeout.ofSeconds(REQUEST_TIMEOUT)).build());
SocketConfig.custom().setSoTimeout(Timeout.ofSeconds(SOCKET_TIMEOUT)).build());
poolingConnectionManager.setDefaultConnectionConfig(
ConnectionConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(CONNECTION_TIMEOUT))
Expand Down
5 changes: 0 additions & 5 deletions httpClients/boot-restclient/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.example.restclient.bootrestclient;

import com.example.restclient.bootrestclient.config.ApplicationProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties({ApplicationProperties.class})
public class BootRestClientApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.restclient.bootrestclient.config;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.validation.annotation.Validated;

@Getter
@Setter
@Validated
@ConfigurationProperties("application")
public class ApplicationProperties {

@NotBlank(message = "External Call URL cant be Blank")
private String externalCallUrl;

@NestedConfigurationProperty private Cors cors = new Cors();

@Getter
@Setter
public static class Cors {
private String pathPattern = "/api/**";
private String allowedMethods = "*";
private String allowedHeaders = "*";
private String allowedOriginPatterns = "*";
private boolean allowCredentials = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.time.Duration;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.client.RestClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpRequest;
Expand All @@ -24,27 +25,33 @@
public class RestClientConfiguration {

@Bean
RestClient restClient(
RestClient.Builder builder,
RestClient restClient(RestClient.Builder restClientBuilder) {
return restClientBuilder.build();
}

@Bean
RestClientCustomizer restClientCustomizer(
ApplicationProperties applicationProperties,
@NonNull BufferingClientHttpRequestFactory bufferingClientHttpRequestFactory) {
String baseUrl = "https://jsonplaceholder.typicode.com";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
DefaultUriBuilderFactory factory =
new DefaultUriBuilderFactory(applicationProperties.getExternalCallUrl());
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.URI_COMPONENT);
return builder.uriBuilderFactory(factory)
.defaultHeaders(
httpHeaders -> {
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(List.of(MediaType.APPLICATION_JSON));
})
.requestFactory(bufferingClientHttpRequestFactory)
.requestInterceptor(
(request, body, execution) -> {
logRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
logResponse(response);
return response;
})
.build();
return restClientBuilder ->
restClientBuilder
.uriBuilderFactory(factory)
.defaultHeaders(
httpHeaders -> {
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(List.of(MediaType.APPLICATION_JSON));
})
.requestFactory(bufferingClientHttpRequestFactory)
.requestInterceptor(
(request, body, execution) -> {
logRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
logResponse(response);
return response;
});
}

private void logResponse(ClientHttpResponse response) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.restclient.bootrestclient.config;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.servers.Server;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@OpenAPIDefinition(
info = @Info(title = "rest-client", version = "v1"),
servers = @Server(url = "/"))
public class SwaggerConfig {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.example.restclient.bootrestclient.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration(proxyBeanMethods = false)
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {

private final ApplicationProperties properties;

@Override
public void addCorsMappings(@NonNull CorsRegistry registry) {
ApplicationProperties.Cors propertiesCors = properties.getCors();
registry.addMapping(propertiesCors.getPathPattern())
.allowedMethods(propertiesCors.getAllowedMethods())
.allowedHeaders(propertiesCors.getAllowedHeaders())
.allowedOriginPatterns(propertiesCors.getAllowedOriginPatterns())
.allowCredentials(propertiesCors.isAllowCredentials());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
spring.application.name=boot-restclient

spring.mvc.problemdetails.enabled=true
spring.threads.virtual.enabled=true
spring.mvc.problemdetails.enabled=true
spring.threads.virtual.enabled=true

application.external-call-url=https://jsonplaceholder.typicode.com

0 comments on commit eb3b605

Please sign in to comment.