How to inject RestTemplate - spring

I am not using xml configurations to define beans. Instead using component scanning and autowire to define and inject dependencies.
RestTemplate is part of springframework. How can I inject this class ?

You do it like any other #Bean in a #Configuration class, and inject with #Autowire - However you question suggest that you should read a little more of the Spring documentation.
#Bean
public RestTemplate restTemplate() {
RestTemplate template = new RestTemplate();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(6);
template.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClients.custom().setConnectionManager(connectionManager).build()));
return template;
}
You almost always want to use it together with Apache HttpClient so you get connection pooling. If you need to use it with self-signed https certificates you need a bit more code (let me know if this is the case)

Related

OpenAPI generator add/generate annotation to ApiClient constructor

I use the newest OpenAPI generator 6.2.1 (https://github.com/OpenAPITools/openapi-generator) to generate an ApiClient with the resttemplate library, which works quite well.
In my application I have now two different RestTemplate beans. So Spring does not know which one to use in the ApiClient constructor.
Parameter 0 of constructor in com.xyz.ApiClient required a single bean, but 2 were found
There is also a hint to solve the problem:
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed
I don't want to mark one of the beans with #Primary because it is not the primary bean wanted to be used.
I would like to add the #Qualifier to the generated ApiClient constructor like this:
#Autowired
public ApiClient(#Qualifier("myClientProperties") RestTemplate restTemplate) {
this.restTemplate = restTemplate;
init();
}
How can I add the #Qualifier annotation to the generated constructor?
I read lots of openapi generator documentation but did not find anything helpful. There is a solution to add a annotation for models (additionalModelTypeAnnotations in the configOptions of OpenApi configuration).
I expect to generate a #Qualifier annotation to the ApiClient constructor.
You can disable the component scanning for the generated classes. Assuming, your root package is 'my.root.package' and you generate the classes into 'my.root.package.generated', annotate your App / Config class with the following:
#ComponentScan(basePackages = "my.root.package",
excludeFilters = #ComponentScan.Filter(type = FilterType.REGEX,
pattern = "my.root.package.generated.*"))
Then, you can create own (qualified) ApiClients based on your rest templates:
#Bean("rest-template-1")
public RestTemplate restTemplate1() {
return new RestTemplate();
}
#Bean("rest-template-2")
public RestTemplate restTemplate2() {
return new RestTemplate();
}
#Bean("api-client-1")
public ApiClient apiClient1(#Qualifier("rest-template-1") RestTemplate restTemplate) {
return new ApiClient(restTemplate);
}
#Bean("api-client-2")
public ApiClient apiClient2(#Qualifier("rest-template-2") RestTemplate restTemplate) {
return new ApiClient(restTemplate);
}
With those different qualified ApiClients, you init your API classes as you need them.

Spring cloud multiple RestTemplate

I am using spring cloud: Spring Boot Application with Eureka + Ribbon default configuration.
I am using 2 RestTemplate configurations, both are #LoadBalanced currently and both of them have the same UriTemplateHandler.
I declared both the #SpringBootApplication and also the #RibbonClient(name="${service.name}") annotations.
My problem is:
When I am trying to access the first configured RestTemplate, the RestTemplate resolvs (by eureka and load balancing by ribbon) to a server , not as I requested as configured in the UriTemplateHandler.
For example: in the UriTemplateHandler I configured "A-Service" and in real time the restTemplate sends the httpRequest to "B-Service"
This behavior happens often, not just for a specific request, but it looks like it only happens when I'm accessing the first configured RestTemplate.
Is it a problem to use 2 RestTemplate with the same uri?
I have no idea why it happens, please advise.
When creating these rest templates as beans, name them uniquely, like e.g.
#LoadBalanced
#Bean("integrationRestTemplate")
public RestTemplate restTemplate() throws Exception {
// build and return your rest template
return ....
}
Then, the other one might be without any specific name e.g.
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
Now, if you have these two distinctive rest templates, you can inject the former one e.g. like that:
#Service
public class MyService {
private final RestTemplate restTemplate;
public ApplicantService(#Qualifier("integrationRestTemplate") RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
// service methods
...
}
Basically, the point is you can choose whatever rest template you want, by specifying a #Qualifier.

spring boot 1.3.3 create multiple resttemplate per env

I am on spring boot 1.3.3 version, I have a requirement where my spring boot application need to call endpoint(s) based on env passed,
which means if env passed as Dev i would need to call devendpoint,
if env passed as Dev1 then need to call dev1endpoint and so on.
So how can I do this ?
Do I need to create multiple restTemplate instances ?
Should I construct the resttemplate dynamically based on env passed ?
As part of constructing resttemplate i would also need to add appllicable interceptor based on env selected.
Plesae suggest.
You can have two beans of the same class. One can be labeled as the primary, and the use on the #Autowired can specify which one to use with the #Qualifier.
Example:
#Configuration
public class MyConfig {
#Bean
#Primary
public RestTemplate typicalConfig() {
// various configs on your rest template
return new RestTemplate();
}
#Bean
public RestTemplate lessTypical() {
// various alternate configurations
return new RestTemplate();
}
}
Now in your service class:
#Service
public class MyService {
#Autowired
RestTemplate typicalRestTemplate;
#Autowired
#Qualifier("lessTypical")
private RestTemplate alternateRestTemplate;
...
}
correct me if I didn't understand your question. I understand that you are going to have different environments but you are going to change this endpoints in runtime depends on some information or whatever, but I don't understand the part when you said you have to create multiple instances of restTemplate for that environments, from my experience on spring boot applications you don't have to do things like that, You just have to create your restTemplate configuration bean.
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
And then injected that object on your services class and do whatever you want with them. I recommend you to read the follow article about restTempalte may this could help you http://www.baeldung.com/rest-template

Whether it is possible to write AOP for Spring RestTemplate class and any external jar classes using spring AOP or Aspectj

Is it possible to write AOP for Spring RestTemplate class using spring AOP or Aspectj. EX:
#Around("execution(* org.springframework.web.client.RestTemplate.getFor*(..))")  
Thanks
I had the same issue and couldn't make it work with AOP.
However, in this case, there is a workaround. Since RestTemplate extends InterceptingHttpAccessor, you can intercept all requests coming through theRestTemplate object.
Sample configuration that logs all HTTP requests :
#Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
// (...)
// setup code for the RestTemplate object
restTemplate.getInterceptors().add((request, body, execution) -> {
logger.info("HTTP {} request to {}", request.getMethod(), request.getURI());
return execution.execute(request, body);
});
return restTemplate;
}
While this is not equivalent to using an aspect, you can get similar functionality with interceptors and pretty minimal configuration.

Cannot inject LoadBalanced annotated OAuth2RestTemplate

I am using Spring Cloud Angel.SR4. My Configuration class for creating an OAuth2RestTemplate bean is as follows:
#Configuration
public class OAuthClientConfiguration {
#Autowired
private MyClientCredentialsResourceDetails resource;
public OAuthClientConfiguration() {
}
#Bean
#Qualifier("MyOAuthRestTemplate")
public OAuth2RestTemplate restTemplate() {
return new OAuth2RestTemplate(this.resource);
}
}
This configuration is totally fine since I am using this RestTemplate in a Feign RequestInterceptor for injecting access tokens to the feign requests. The problem is that when I annotate an autowired OAuth2RestTemplate with #LoadBalanced the dependency injection engine raises a NoSuchBeanDefinitionException exception. For example, the following would raise an exception:
#LoadBalanced
#Autowired
#Qualifier("MyOAuthRestTemplate")
private OAuth2RestTemplate restTemplate;
and when I remove the #LoadBalanced, everything works fine. What is wrong with #LoadBalanced? Do I need any additional configurations (I already have #EnableEurekaClient)?
I found a workaround. The problem was that I had misunderstood the #LoadBalanced annotation. This is just a qualifier for the auto-created load-balanced RestTemplate bean, and it would not create a proxy around the annotated RestTemplate for injecting the load balancing capability.
After seeing this https://github.com/spring-cloud/spring-cloud-commons/blob/v1.0.3.RELEASE/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerAutoConfiguration.java, I revised my OAuth2RestTemplate bean definition as follows, and it solved the problem.
#Bean
#Qualifier("MyOAuthRestTemplate")
public OAuth2RestTemplate restTemplate(RestTemplateCustomizer customizer) {
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(this.resource);
customizer.customize(restTemplate);
return restTemplate;
}
I used #LoadBalanced with restTemplate in spring cloud with ribbon behind the scenes.
adding #LoadBalanced in the bean definition it works
like this:
in my class i have
#Autowired
#LoadBalanced
#Qualifier("bookRepositoryServiceRestTemplate") private RestTemplate bookRepositoryServiceRestTemplate;
and in my configuration class i have:
#Configuration
public class ServiceConfig {
#Bean
#LoadBalanced
public RestTemplate bookRepositoryServiceRestTemplate(SpringClientFactory clientFactory, LoadBalancerClient loadBalancer){
RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory = new RibbonClientHttpRequestFactory(clientFactory,loadBalancer);
return new RestTemplate(ribbonClientHttpRequestFactory);
}
....
}
this works for me
I hope that this can help

Resources