I have a #ApplicationScoped bean in my Helidon MP microservice, is there a way to force the creation of the bean at server startup instead at first method call?
I need this bean ready and running just after server startup but every attempt I made it's inconclusive
I found a way to solve it.
If your bean observes the initialization of ApplicationScoped it will be instantiated during startup phase. It's a trick but it works fine.
public void init(#Observes #Initialized(ApplicationScoped.class) Object init) {
}
Related
I recently update my spring boot app 2.1.9 to 2.2.0 and i'm facing a problem. When i'm calling "configprops" from actuator endpoint, an exception is throw :
Scope 'job' is not active for the current thread
I reproduce the bug : https://github.com/guillaumeyan/bugspringbatch (just launch the test). Original project come from https://github.com/spring-guides/gs-batch-processing/tree/master/complete
I tried to add :
#Bean
public StepScope stepScope() {
final StepScope stepScope = new StepScope();
stepScope.setAutoProxy(true);
return stepScope;
}
but it does not work (with spring.main.allow-bean-definition-overriding=true)
Here is my configuration of the spring batch
#Bean
#JobScope
public RepositoryItemReader<DossierEntity> dossierToDiagnosticReader(PagingAndSortingRepository<DossierEntity, Long> dossierJpaRepository, #Value("#{jobParameters[origin]}") String origin) {
RepositoryItemReader<DossierEntity> diagnosticDossierReader = new RepositoryItemReader<>();
diagnosticDossierReader.setRepository(dossierJpaRepository);
diagnosticDossierReader.setMethodName("listForBatch");
// doing some stuff with origin
return diagnosticDossierReader;
}
ExceptionHandlerExceptionResolver[199] - Resolved [org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'scopedTarget.dossierToDiagnosticReader': Scope 'job' is not active for the current thread;
consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for job scope]
I downloaded your project and was able to reproduce the case. There are two issues with your example:
You are defining a job scoped bean in your app but the JobScope is not defined in your context (and you are not using #EnableBatchProcessing annotation that adds it automatically to the context). If you want to use the job scope without #EnableBatchProcessing, you need to add it manually to the context.
Your test fails because there is no job running during your test. Job scoped beans are lazily instantiated when a job is actually run. Since your test does not start a job, the bean is not able to be proxied correctly.
Your test does not seem to test a batch job, I would exclude the job scoped bean from the test's context.
Bug resolve in spring boot 2.2.1 https://github.com/spring-projects/spring-boot/issues/18714
I have an Java EE project running Wildfly 10.1 Final.
I am creating some timers programmatically using javax.ejb.TimerService like this:
timerService.createTimer(new Date(), null);
And now, I am trying to cancel those timers the next time the project is deployed, because they are still there every time I re-deploy the project, or restart the server.
I tried to use a Singleton Startup bean for that, like this:
#Startup
#Singleton
public class TimerKiller {
#PostConstruct
public void killTimers() {
timerService.getAllTimers().forEach(timer -> timer.cancel());
}
#Resource
TimerService timerService;
}
But, I get an exception:
java.lang.IllegalStateException: WFLYEJB0325: Cannot invoke timer
service methods in lifecycle callback of non-singleton beans
This is the last exception in the stack trace (the last Caused By).
I can't seem to understand what does this mean. I tried googling but nothing comes up.
Did you use javax.ejb.Singleton or javax.inject.Singleton. Make sure you are using javax.ejb.Singleton.
You can also use a e.g. SingleActionTimer and specify it as non-persistent:
TimerConfig tc = new TimerConfig(null, false);
timerService.createSingleActionTimer(new Date(), tc);
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.
I have been running in to problems making sure that a spring application context that i am destroying has completely gone away, and cant see the object being garbage collected. When i look at the instance in VisualVM i can see that there are a number of outstanding references to both the context and it's bean factory that remain once the context is closed and destroyed. These all to be in relation to the initial set up of the bean factory (during the refresh method of AbstractApplicationContext) which registers the bean factory and the context with various bean post processors etc.
There do not appear to be any methods on the bean factory or on the application contexts (even the refreshable ones) that do more than remove the lowest level reference to the bean factory. The result is that it appears to be leaking memory, and in certain circumstances preventing the clean re-creation of a context.
I am asking as the software i am working on at the moment may dynamically create / destroy and then re-create the context (as modules are dynamically loaded and unloaded) and the leftover elements of the context and bean factory are causing problems with components such as spring-data-jpa (especially the proxy that binds the repository interfaces to the repository implementations).
Does anyone know of a way whereby i can cleanly and completely remove a context and bean factory without having to completely close down the VM that initially created it?
Having looked into this again recently, i noticed that i was overriding the doClose() method of the context to make sure beans were completely destroyed, but was not calling the super.doClose() method, which meant that LiveBeansView.unregisterApplicationContext() / destroyBeans() / getLifecycleProcessor().onClose() and closeBeanFactory() were not being called.
I added this in, and (most) if not all contexts are now cleanly destroyed and garbage collected. I will assume that any outstanding contexts that are not destroyed are more probably issues in our own code with dangling references.
If you are using Spring's IoC container in a non-web application environment; for example, in a rich client desktop environment; you register a shutdown hook with the JVM. Doing so ensures a graceful shutdown and calls the relevant destroy methods on your singleton beans so that all resources are released. Of course, you must still configure and implement these destroy callbacks correctly.
To register a shutdown hook, you should call the registerShutdownHook() method that is declared on the AbstractApplicationContext class:
Code
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class startup {
public static void main(final String[] args) throws Exception {
AbstractApplicationContext ctx
= new ClassPathXmlApplicationContext(new String []{"beans.xml"});
// add a shutdown hook for the above context...
ctx.registerShutdownHook();
// app runs here...
// main method exits, hook is called prior to the app shutting down...
}
}
Call destroy on context and set null to all variables referencing instance of your application context:
AbstractApplicationContext context = new ClassPathXmlApplicationContext(new String []{"beans.xml"});
// ... do your stuff
context.destroy();
context = null;
I would like to make some clean up on a bean when I shutdown a CDI application. For example, I would like to close an IO connection. Of course, here, the bean is marked as #ApplicationScoped.
To manage this I wrote an extension and observe the BeforeShutdown event, and then I select my bean to call a clean up method :
public void beforeShutdown(#Observes BeforeShutdown beforeShutdown) {
SomeBean obj = CDI.current().select(SomeBean.class).get();
obj.cleanup();
}
My problem is that I have access to a new instance in this method. Not the instance I got in the whole application.
If you want to see this instance problem, I've made a repo on github to show it : https://github.com/hasalex/cdi-extension-demo.
So I have 2 questions :
Why do I get a new instance ?
Is there an other way to cleanup my bean at the end of the application ? (in SE and in WildFly environments)
look here: http://docs.jboss.org/cdi/spec/1.1.EDR1/html/spi.html#provider
11.5.4. BeforeShutdown event
The container must fire a final event after it has finished processing requests and destroyed all contexts.
Maybe you want to use #PreDestroy: http://docs.oracle.com/javaee/6/tutorial/doc/gmgkd.html
Annotate the declaration of the method with the javax.annotation.PreDestroy annotation.
CDI calls this method before starting to destroy the bean.