1

I have a OAuth2RestTemplate defined as below

@Configuration
@EnableOAuth2Client
public class TestOauth{
        
@Bean
public OAuth2RestTemplate restTemplate(){
OAuth2RestTemplate restTemplate= new OAuth2RestTemplate(buildResourceDetails());
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new 
HttpComponentsClientHttpRequestFactory()));
return restTemplate;
}
    
@Bean
public ClientCredentialsResourceDetails buildResourceDetails(){
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setClientId("TestId");
resourceDetails.setClientSecret("TestSecret");
resourceDetails.setAccessTokenUri("TestURI");
return resourceDetails;
}

Now, in the calling class, I have it annotated as below and it works fine.

@Autowired
private OAuth2RestTemplate restTemplate;

I want to make this functionality generic and create the templates based of off clientId, secret and URI. How can I achieve this? Is creating multiple @bean methods (Separate method for each credentials) and based on the caller credentials, picking the corresponding bean from a map maybe the only way to achieve this?

I tried keeping only one @bean method and passing params to restTemplate method but I keep running into No qualifying bean of type [java.lang.String] found error

Please advise

user3097172
  • 41
  • 1
  • 4

1 Answers1

1

If you have a few number of clientId such as 3 or 4 it's ok to have multiple bean of type OAuth2RestTemplate with different name and use them. if you want to go for this approach read the following link to autowire multiple bean in a map:

Spring Autowire Bean with multiple Interface Implementations, define Implementation in method

But if you know the number of ClientId will dynamically change based on some parameters you can use one bean of type OAuth2RestTemplate and change the value of clientId header at runtime using RestTemplate Interceptor.

Read the following link to know how to use Interceptor:

https://howtodoinjava.com/spring-boot2/resttemplate/clienthttprequestinterceptor/

If you are determined to pass client Id at runtime based on parameter in request you can do that this way:

private HttpHeaders createHttpHeaders(String clientId, String secret)
{
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.add("client_id", clientId);
    headers.add("client_secret", secret);
    return headers;
}

private void yourserviceMethod() 
{
    String theUrl = "http://blah.blah.com:8080/rest/api/blah";
    try {
        HttpHeaders headers = createHttpHeaders("clintId", "secret", "accessToken");
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<String> response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, String.class);
        System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
    }
    catch (Exception eek) {
        System.out.println("** Exception: "+ eek.getMessage());
    }
}
Tashkhisi
  • 2,070
  • 1
  • 7
  • 20
  • Super.. similar to soap handlers right? Let me check it out thanks. – user3097172 Jul 28 '20 at 21:46
  • Actually the interceptor won't work since the credentials are selected based on certain conditions and not are not stored in a property file. – user3097172 Jul 29 '20 at 19:47
  • You mean you want to decide which `clientId` to be set as header in your service? If it is your requirement you can set `clientId` as header when calling Restemplate methods in your service – Tashkhisi Jul 29 '20 at 20:16
  • How can I pass the clientid to interceptor at runtime? – user3097172 Jul 29 '20 at 20:30
  • I cannot distinguish which clientid to choose from based on the details from the request in interceptor. – user3097172 Jul 29 '20 at 21:21
  • Can I just not have EnableOAuth2Client, Configuration and Bean annotations and just use a regular factory pattern to return the OauthRestTemplate. Would that work? – user3097172 Jul 29 '20 at 22:59
  • I don't know what type of token your are using but I've just edited my answer to show you how set `clientId` at runtime., if it doesn't work for you don't hesitate to ask your question – Tashkhisi Jul 30 '20 at 06:11