Spring boot with #RefreshScope #PostConstruct #PreDestroy - java

In my Spring boot application, we utilize #RefreshScope for dynamic reloading of beans after configuration changes. It works, but I have encountered an issue when combining the #RefreshScope on beans with methods annotated #PostConstruct and #PreDestroy. It seems the #PostConstruct is not called after refresh.
When booting the app, the #PostConstruct method is called normally. When invoking refresh, the #PreDestroy method gets invoked normally as well, and I would expect #PostConstruct to be called on the new proxied bean instance, but it is not. There is important init/destroy-logic going on in these methods, so not having them called is a problem.
Anyone encountered the same problem, and is this a bug or a "feature"? Is there a way to make this work?
Best regards

I faced the same problem today and was able to solve it by calling a method on the #RefreshScope'd bean after the refresh. To accomplish this, I added an event handler for the RefreshScopeRefreshedEvent to the affected bean:
#EventListener
public void onRefreshScopeRefreshed(final RefreshScopeRefreshedEvent event) {
getClass();
}
As you can see it's a quite meaningless implementation, but nevertheless this method call on the bean triggers its initialization (the #PostConstruct method).
This behaviour conforms to the documentation:
Refresh scope beans are lazy proxies that initialize when they are used (i.e. when a method is called),
But still I think that it's really a bug and that #PostConstruct should be called automatically after a refresh.

Related

Refreshing #Resource and #Autowired bean at Runtime

I have one bean which is define in the SpringConfiguration and which gets initialised at the startup.
This bean(Map) is populated by querying the database at startup.
Now the database gets update frequently and I have implemented the ApplicationListener and was trying to implement a cache using TimerTask.
The code of timertask runs fine and in that i am accessing the bean using ApplicationContext but not able to refresh/reinitialize the bean with the new database results.
The #Resource and #Autowired beans still shows the old value.
I want to refresh/Reinitialize the #Autowired / #Resource bean at Runtime. Please advise
If you are using an ORM it should handle it for you.
Otherwise, if you are doing it on you own, you can annotate the bean with #RefreshScope and when you detect a change (wherever method you are using like cron or listener) then just refresh the context from the actuator like:
http://localhost:8080/actuator/refresh
Cheers!
pd: Actuator should be enabled and accesible.

Spring lazy loading after bean is really called

I would like to have a (singleton) bean initialized only after it is actually used (instead of when it is only autowired). Let say I have a Client that I want to initialize only when I want to call any of its methods
#Component
#Lazy(true)
public class Client {
#PostConstruct
void init() {}
void action(){}
}
And I have a Service class that sometimes use it (and maybe sometimes not).
#Service
public class Service {
#Autowired
Client client;
void action1WithClient(){}
void action2WithClient(){}
void actionWithoutClient(){}
}
As it is now, the client is initialized right on the application startup without actually being used due to #Autowired and the fact that Service is eagerly loaded.
Currently only solution that comes to my mind is to do kind of double-checked locking with explicitly asking for Client bean from spring application context when someone tries to use (ie. without #Autowired) or (maybe even better) to do "manual" lazy loading inside the Client.
Question: Is there a "spring" way to postpone the initialization of client until any of its method is actually called (e.g. something like lazy loading is working for hibernate collections)?
I am using Spring 4.
Ah, ok, I should read the javadoc more properly... Solution seems to add anotation "each" autowired dependeny:
#Autowired
#Lazy
Client client;
Anyway - if anybody knows if it is possible to omit such declarations, since it might be error prone - one can easily forget to use #Lazy at each injection point.
Edit:
The easiest way is #ComponentScan(lazyInit = true, basePackages=...).
Previous answer:
There is http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/aop/target/LazyInitTargetSource.html
A bean wrapped with LazyInitTargetSource will not be created until the first actual usage.
How to nicely wrap most of your beans with this wrapper? One possible way is to create your own BeanFactoryPostProcessor...

How to get transactions to a #PostConstruct CDI bean method

I'm experimenting with Java EE 7, CDI, JPA and JSF.
When the webapp starts, I would like to run an initialization method in my CDI bean (marked with #PostConstruct) that does some work with the database (inserts some rows etc..). For this I need a transaction, but this wasn't as easy as I expected.
I have tried adding #Transactional annotation to my method, but apparently it only works with EJB. I actually tried converting my bean to EJB instead of CDI bean, but I still didn't get transaction to my #PostConstruct method. It worked with other methods in the bean, but not with my #PostConstruct initialization method.
Then I read about creating method interceptor to get transactions to CDI beans:
http://eubauer.de/kingsware/2012/01/16/cdi-and-transactions-e-g-in-jboss-7-0-2/
I tried this too, but no luck. It doesnt work either.
So how does one get transactions to a #PostConstruct initialization method in a CDI bean?
Apparently it seems that:
In the #PostConstruct (as with the afterPropertiesSet from the InitializingBean interface)
there is no way to ensure that all the post processing is already done, so (indeed) there
can be no Transactions. The only way to ensure that that is working is by using a
TransactionTemplate.
So the only way to do something with the database from the #PostConstruct is to do something like this:
#Service("something")
public class Something
{
#Autowired
#Qualifier("transactionManager")
protected PlatformTransactionManager txManager;
#PostConstruct
private void init(){
TransactionTemplate tmpl = new TransactionTemplate(txManager);
tmpl.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
//PUT YOUR CALL TO SERVICE HERE
}
});
}
}
NOTE: similar thread but referencing Spring framework #Transactional on #PostConstruct method

How to properly shutdown executor services with Spring?

I have a command line application that uses a Spring-managed bean that's composed of a java ExecutorService created with:
ExecutorService service = Executors.newFixedThreadPool(4);
Now, I want my service to shutdown when my application shuts down, so I made my bean implement the DisposableBean interface and have a destroy method such as:
public void destroy(){
service.shutdown();
}
Then I might be tempted to do something like register a shutdown hook on the Spring context. However I found out (the hard way, i.e., in a pre-production release) that this doesn't work: the shutdown hook doesn't get called before the ExecutorService.shutdown() method is called, causing a classic catch 22 problem (it does get called on interruption, i.e., if I hit Ctrl-C while the application is running). This escaped my unit tests because for some reason it seems to work fine from within JUnit, which is still puzzling me: what does JUnit do differently?
The solution I found so far is to explicitly call ApplicationContext.close() right before I exit my main function. I was wondering if there was a better solution to this and what are the best practices for having flexible thread pools managed by Spring. Also what if my bean is not directly managed by Spring but is created by a bean managed by Spring? Should I just cascade the calls to destroy()? Wouldn't this be very error prone?
I appreciate any comments, suggestions, further reading, RTFMs, magic recipes.
Thanks!
Are you aware that this:
ExecutorService service = Executors.newFixedThreadPool(4);
can be replaced with this:
<bean id="service" class="java.util.concurrent.Executors"
factory-method="newFixedThreadPool" destroy-method="shutdown">
<constructor-arg value="4"/>
</bean>
The spring context then manages, more directly, the shutdown of your executor service--and it can be more easily reused.
Per official Spring documentation, when using annotation-based configuration, for destroyMethod field of #Bean, Spring's default behavior is to automatically invoke public, no-arg methods named close or shutdown when the application context is being closed.
As a convenience to the user, the container will attempt to infer a
destroy method against an object returned from the #Bean method. For
example, given an #Bean method returning an Apache Commons DBCP
BasicDataSource, the container will notice the close() method
available on that object and automatically register it as the
destroyMethod. This 'destroy method inference' is currently limited to
detecting only public, no-arg methods named 'close' or 'shutdown'. The
method may be declared at any level of the inheritance hierarchy and
will be detected regardless of the return type of the #Bean method
(i.e., detection occurs reflectively against the bean instance itself
at creation time).
To re-iterate, this is the default behavior for annotation-driven configuration when a destroy method is not explicitly set. If this behavior is undesired explicitly setting destroy method to an empty string will disable this "feature":
To disable destroy method inference for a particular #Bean, specify an
empty string as the value, e.g. #Bean(destroyMethod=""). Note that the
DisposableBean and the Closeable/AutoCloseable interfaces will
nevertheless get detected and the corresponding destroy/close method
invoked.
On the other hand, when using XML configuration, this is not the default behavior... To achieve parity, destroy-method can be explicitly set to (inferred). Refer to the Destruction callbacks and Default initialization and destroy methods sections in the official docs for details.
Consider using Spring's TaskExecutor, which can be configured with a thread pool.
http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html
Just want to add the config based ExecutorService bean creation to #Keith's answer
#Bean("fixedThreadPool")
public ExecutorService fixedThreadPool() {
return Executors.newFixedThreadPool(THREAD_POOL_SIZE);
}

Executing a Java class at application startup using Spring MVC [duplicate]

This question already has answers here:
Execute method on startup in Spring
(13 answers)
Closed 6 years ago.
What is the best way to execute a Java class at application startup using Spring MVC ?
There's not necessarily a "best" way. As usual, there are many ways to do it, and the "best" is whichever fits into your project the best:
Use init-method="..." on a bean element in XML, as cjstehno mentioned
Implement Spring's InitializingBean interface. When deployed in an ApplicationContext, the afterPropertiesSet() method will be called when the bean is created.
Annotate a method on a bean with #PostConstruct. Again, if deployed to an ApplicationContext, the annotated method will be called when the bean is created.
If your bean is more of an infrastructure bean to be tied into the Spring lifecycle, implement ApplicationListener<ContextRefreshedEvent>. The onApplicationEvent(..) method will be called during Spring's startup, and you can do whatever work you need there.
Assuming your context is loaded on startup, create a bean in your spring application context with an init method explicitly called out in the XML config (or implement Springs InitializingBean). If you have lazy-loading enabled you will need to make sure this bean is not lazy.
<bean name="starter" init-method="start" class="com.my.StarterBean" lazy="false" />
(please double-check the params in the docs).
If your context is not loaded on startup you can register an server context listener (part of Servlet API, not Spring).
You can use either implementations:
1) Implement interface InitializingBean. This approach is granted load all your beans then call afterPropertiesSet method.
#Override
public void afterPropertiesSet() throws Exception {
init();
}
2) Using JSR-250's Annotation #PostConstruct. This approach will not wait for spring beans to load.
#PostConstruct
public void init() {
}

Categories