Search code examples
javaspringoauth-2.0webclient

WebClient do it myself


I'm following this lesson here : https://www.baeldung.com/spring-webclient-oauth2 I'm trying to build a service class to access a resource from other API with given clientId & clientSecret (tested in Postman & Swagger).

Next, we'll set the webClient instance that we autowired in our scheduled task:

@Bean
WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) {
    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
      new ServerOAuth2AuthorizedClientExchangeFilterFunction(
        clientRegistrations,
        new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
    oauth.setDefaultClientRegistrationId("otherClientId");
    return WebClient.builder()
      .filter(oauth)
      .build();
}
 

I got a bit confused , and wonder where should I put these code? should I put it in a class WebClient.java in my project's config package?

i tried to put these code in my service class , and i get this error message :

nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: 
Error creating bean with name 'xxxService': Requested bean is currently in creation: 
Is there an unresolvable circular reference? 

the code in my xxxService class is like this:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.security.oauth2.client.web.server.UnAuthenticatedServerOAuth2AuthorizedClientRepository;

@Slf4j
@Service
public class xxxService{
  @Autowired
  private WebClient wclient;
  
  public void getAuthThenGetResource(){
    ... 
    log.info("got token");
    ...
    log.info("got response");
  }
}

many thank's for the help.


Solution

  • While you can declare Spring Beans in a Service class, it should be be declared in a separate Configuration class. Moreover, you get the error because you are autowiring the bean in the same service it is declared in.

    There are a couple ways you can fix this. One is using the convention of defining a Configuration class like the following. Ideally this class would also go in a different package in your project structure.

    @Configuration
    class ApplicationConfiguration {
      @Bean
      WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) {
          ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
            new ServerOAuth2AuthorizedClientExchangeFilterFunction(
              clientRegistrations,
              new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
          oauth.setDefaultClientRegistrationId("otherClientId");
          return WebClient.builder()
            .filter(oauth)
            .build();
      }
    }
    

    The other one, which I'm not going to show, is by calling the bean declaration function (i.e. webClient(clientRegistrations)) with a ReactiveClientRegistrationRepository which you can Autowire instead of the WebClient. This is NOT the right way to do it. I just wanted to mention other ways of dealing with dependency injection errors.