Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot WebClient Builder initialization in ServiceImpl Constructor

I am trying to follow the best practise of autowiring Webclient using WebClient Builder but little confused.

Here is my Main Application in which i am producing a Webclient Builder and autowiring it in one of my service class

 @SpringBootApplication
    public class MyApplication {
        @Bean
        public WebClient.Builder getWebClientBuilder() {
            return WebClient.builder();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }}


ServiceImpl Class

    public class MyServiceImpl implements MyService {
        private static final String API_MIME_TYPE = "application/json";
        private static final String API_BASE_URL = "http://localhost:8080";
        private static final String USER_AGENT = "Spring 5 WebClient";
        private static final Logger logger = LoggerFactory.getLogger(MyServiceImpl.class);
    
        @Autowired
        private WebClient.Builder webClientBuilder;
    
        @Override
        public Mono<Issue> createIssue(Fields field) {
            return webClientBuilder.build()
                    .post()
                    .uri("/rest/api/")
                    .body(Mono.just(field), Fields.class)
                    .retrieve()
                    .bodyToMono(Issue.class);
        }}

I am trying to build the webClientBuilder with BaseURl, DefaultHeader etc. I tried to initialize it inside MyServiceImpl Constructer but not sure if its correct or not.

public MyServiceImpl() {
            this.webClientBuilder
                    .baseUrl(API_BASE_URL).defaultHeader(HttpHeaders.CONTENT_TYPE, API_MIME_TYPE)
                    .defaultHeader(HttpHeaders.USER_AGENT, USER_AGENT)
                    .build();
        } 

Am i doing it correct or is there a better way to do it.

Currently I have 2 ServiceImpls to call Different Apis and thats the reason i tried to set the 'baseurl' and other defaults in service itself.

Please Help. TIA

like image 554
Kamal Garg Avatar asked Mar 01 '23 23:03

Kamal Garg


1 Answers

Usually, your approach would be something like this:

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

@Configuration
public class MyApplicationConfiguration {
    
    @Bean
    public WebClient myWebClient(WebClient.Builder webClientBuilder) {
        return webClientBuilder
                .baseUrl(API_BASE_URL)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, API_MIME_TYPE)
                .defaultHeader(HttpHeaders.USER_AGENT, USER_AGENT)
                .build();
    }
}

@Service
public class MySericeImpl implements MyService {

    @Autowired
    private WebClient myWebClient;

    @Override
    public Mono<Issue> createIssue(Fields field) {
        return myWebClient
                .post()
                .uri("/rest/api/")
                .body(Mono.just(field), Fields.class)
                .retrieve()
                .bodyToMono(Issue.class);
    }
 }

The key thing to remember is that WebClient.Builder is already pre-configured for you and Bean is already created. So you just need to autowire it, adjust the configuration and build final WebClient.

It is also possible to use another approach to configure it. There are 3 main approaches to customize WebClient. See official docs for more details https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-webclient.


Edit for consuming more APIs - configure multiple WebClients and autowire them in an appropriate service class.

@Configuration
public class MyApplicationConfiguration {
    
    @Bean
    public WebClient myWebClientForApi1(WebClient.Builder webClientBuilder) {
        return webClientBuilder
                .clone()
                .baseUrl(API_1_BASE_URL)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, API_MIME_TYPE)
                .defaultHeader(HttpHeaders.USER_AGENT, USER_AGENT)
                .build();
    }

    @Bean
    public WebClient myWebClientForApi2(WebClient.Builder webClientBuilder) {
        return webClientBuilder
                .clone()
                .baseUrl(API_2_BASE_URL)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, API_MIME_TYPE)
                .build();
    }
}
like image 93
rasto Avatar answered Mar 05 '23 05:03

rasto