How does spring work when class is not a spring managed bean but an object referred inside is - spring

I have a RestTemplate Bean in a spring application like this
#Bean
public RestTemplate createRT(HttpClient httpClient) {
return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
}
Note that HttpComponentsClientHttpRequestFactory isn't a spring managed bean.
HttpClient bean is created as follows:
#Bean
public CloseableHttpClient createHttpClient(PoolingHttpClientConnectionManager poolingConnectionManager, RequestConfig rc) throws NoSuchAlgorithmException {
CloseableHttpClient httpClient = HttpClientBuilder
.create()
.setConnectionManager(poolingConnectionManager)
.setDefaultRequestConfig(rc)
.build();
return httpClient;
}
Note that both PoolingHttpClientConnectionManager and RequestConfig are created as spring managed beans.
My question is that in my case, the http client factory object i.e. HttpComponentsClientHttpRequestFactory isn't a spring managed bean but all it's internal objects that it uses to create an HttpClient object for connections are spring managed beans.
So will the HttpClient object that this factory creates going to be a singleton and managed by Spring ? Also would this implementation be considered erroneous in any sense based on the outer object being jvm managed and all inner objects being spring managed ?
I am little confused with it.

There should be no problem with the given snippet with respect to beans lifecycle. You are right that bean HttpComponentsClientHttpRequestFactory will not be Spring managed, but it would still be singleton, because the it is created inside a bean RestTemplate which is singleton. Note that RestTemplate bean would be created with name createRT.
Now coming to the point if it's considered erroneous: Although this is suggested that you should leave the bean and its dependency to be managed by Spring container. But for simple dependencies like in this case, I have seen developers create bean dependencies this way all the time, and everything works just well.
So, if you can, you should make this as a separate bean and let it come as a dependency for bean RestTemplate.

Related

spring-kafka starting another container with #RefreshScope annotation

I am integrating my spring-kafka consumer with spring-cloud. Here is the bean that basically has the #KafkaListener
#ConditionalOnMissingBean
#Bean
#RefreshScope
SinkGenericKafkaConsumer<String, MessageEvent, MessageEntity> sinkGenericKafkaConsumer(final ContainerConfigProperties containerConfigProperties,
DataSource dataSource,
final SinkKafkaConsumerProperties<MessageEvent, MessageEntity> kafkaConsumerProperties) {
return new SinkGenericKafkaConsumer<>(containerConfigProperties, kafkaConsumerProperties, dataSource);
}
So when I make a config change and context gets refreshed I was hoping that since I am using #RefreshScope when beans are refreshed spring-kafka framework will use the new bean that gets created, but it spawns the new bean as a new container so now I have 2 containers which is not the desired thing. May be I am doing something wrong but can't figure out. Also the datasource i am injecting is not getting refreshed even though it has #ConfigurationProperties annotated.

Spring Ribbon #LoadBalanced doesn't work with #scope("prototype") for restTemplate

I'm following the official spring ribbon guide, and I noticed one thing.
If a RestTemplate is being created in this way :
#LoadBalanced
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) ---- I added this line
RestTemplate restTemplate(){
logger.warn("create a restTemplate bean..."); --- added this for debug
return new RestTemplate();
}
Then the ribbon client will not be able to find server. (unable to parse client name with server IP address);
I debugged into bean creation process, and noticed that the message, "create a restTemplate bean...", has appeared twice in the log.
And the auto wired restTemplate instance doesn't have a LoadBalancerInterceptor, which is probably why it fails.
So I wonder if there is any suggestion to fix this issue?
P.S: I need RestTemplate to be prototype so that I can set different errorHandlers.
It really fails because of the missing LoadBalancerInterceptor, but the class can be simply injected.
Inject it, and take the #LoadBalanced annotation away:
java
#Bean
#Scope("prototype")
RestTemplate loadBalancedTemplate(LoadBalancerInterceptor loadBalancerInterceptor) {
RestTemplate template = new RestTemplate();
template.getInterceptors().add(loadBalancerInterceptor);
return template;
}
As mentioned by the author:
It turns out that #LoadBalanced annotation won't retrieve a RestTemplate bean from the application context, with 'prototype' scope, it will simply retrieve a new instance, which is not used by any autowired field.

Spring boot activemq overriding the connection factory

I am new to Spring boot and i am trying to lookup my own connection factory instead of using the default 'ConnectionFactory' which Spring boot provides and also trying to lookup the already defined queue without using dynamicqueues.
How can i do that?
Should i add jndi.properties file and add it there so i can lookup?
Can someone suggest?
The Spring Integration configuration by default is looking for a
Spring Bean called ‘connectionFactory’.
Spring Boot by default,
creates the JMS connection factory using the name
‘jmsConnectionFactory’.
#Bean
public ConnectionFactory jmsConnectionFactory() {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
return connectionFactory;
}
https://github.com/spring-projects/spring-boot/blob/v1.5.9.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQConnectionFactoryConfiguration.java

Spring MVC: How autowiring of HttpSession works?

I would like to know how autowiring of HttpSession works.
If we declare like below:
#Autowired
private HttpSession httpSession;
When exactly in the Spring workflow, httpSession variable declared above will be initialized with request.getSession(true)?
I don't understand why you want to autowire HttpSession but here is how autowiring works.
To Autowire a class you need to specify it as a bean either by using annotations (#Controller, #Service, #Repository, #Component) or by declaring #Bean in config class. Once you define a bean Spring autowires or constructs the objects when the spring context initializes (during server startup for webapp and you explicitly initialize spring context in case console/standalone app).
Since HttpSession can only be fetched from HttpServletRequest object, you cannot initialize it during application startup because there is no HttpServletRequest during startup. If you want some logic to implement before fetching the HttpSession you can create a util method like this
public getHttpSession(HttpServletRequest request) {
// put your logic here and return session object
}

Using session-scoped object in singleton in Spring

I have a problem with one of my beans. I have a bean, which has a singleton scope and second bean which has session scope.
I'm using java based config in my spring app, I added proxy mode to my session scope bean, but it throws exception when I'm tryign to use that (session scoped) bean:
Method threw 'org.springframework.beans.factory.BeanCreationException' exception. Cannot evaluate my-bean-full-name$$EnhanceBySpringCGLIB#ID.toString()
From what I have read here http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-other-injection-proxies
I thought that only thing which I have to do is to add
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
to my bean class (which also has #Component annotation and it is scanned by Spring)
The thing which I was missing was this line in my web app initializer:
servletContext.addListener(new RequestContextListener());
After that, bean has been injected

Resources