Stopping Invokation of Spring Quartz Job on spring context loading - spring

My application has got multiple Jobs which needs to be executed programatically when user wants.
I have implemented all the Jobs using MethodInvokingJobFactoryBean and the issue is whenever my spring context gets loads up all the Jobs gets fired.
How to stop the execution of Job on spring context loading ??
Thanks in advance
Ajay

I assume you have problem because your job calls beans which has not been initialized?
Then you will be interested in depends-on attribute on bean element.
You can also set startupDelay property on SchedulerFactoryBean.

Related

Is there any valid reason for declaring a Quartz Job as a spring bean?

By looking at some examples of running quartz jobs in a spring boot app, I see many of them are actually declaring the Job with the #Component annotation :
Baeldung example
Dzone example
Medium example
It seems to be completly useless as the job factory will create a new instance every time the job is triggered.
I can see in my app that the method SpringBeanJobFactory.createJobInstance is called each time the job is executed. I removed the #Component annotation and it works perfectly, so is there any advantage of declaring a Job as a spring bean ?

What is difference between ContextRefreshedEvent, ContextStartedEvent, ContextStoppedEvent and ContextClosedEvent

In Spring 5.x, what is the difference between following events?
ContextRefreshedEvent
ContextStartedEvent
ContextStoppedEvent
ContextClosedEvent
Which event correlate with the servlet context events (as per https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html):
ServletContextListener.contextInitialized(ServletContextEvent); and
ServletContextListener.contextDestroyed(ServletContextEvent)?
I have the following situation:
In want to initialize a logging subsystem as soon as possible, should that be done in ContextRefreshedEvent or ContextStartedEvent?
I also want to destruct it as late as possible, should that be done in ContextClosedEvent or ContextStoppedEvent?
The documentation for these built-in events can be found here, specifically:
ContextRefreshedEvent
Published when the ApplicationContext is initialized or refreshed (for example, by using the refresh() method on the ConfigurableApplicationContext interface). Here, “initialized” means that all beans are loaded, post-processor beans are detected and activated, singletons are pre-instantiated, and the ApplicationContext object is ready for use. As long as the context has not been closed, a refresh can be triggered multiple times, provided that the chosen ApplicationContext actually supports such “hot” refreshes. For example, XmlWebApplicationContext supports hot refreshes, but GenericApplicationContext does not.
ContextStartedEvent
Published when the ApplicationContext is started by using the start() method on the ConfigurableApplicationContext interface. Here, “started” means that all Lifecycle beans receive an explicit start signal. Typically, this signal is used to restart beans after an explicit stop, but it may also be used to start components that have not been configured for autostart (for example, components that have not already started on initialization).
ContextStoppedEvent
Published when the ApplicationContext is stopped by using the stop() method on the ConfigurableApplicationContext interface. Here, “stopped” means that all Lifecycle beans receive an explicit stop signal. A stopped context may be restarted through a start() call.
ContextClosedEvent
Published when the ApplicationContext is closed by using the close() method on the ConfigurableApplicationContext interface. Here, “closed” means that all singleton beans are destroyed. A closed context reaches its end of life. It cannot be refreshed or restarted.
RequestHandledEvent
A web-specific event telling all beans that an HTTP request has been serviced. This event is published after the request is complete. This event is only applicable to web applications that use Spring’s DispatcherServlet.
Afaik, none of these correlate directly to the ServletContext. That's a different beast than Spring's application context, and there are separate events for that.
Setting up and tearing down a logging system can be complicated and will depend on which logging system you use. In short, you may want to try with ContextRefreshedEvent and ContextClosedEvent. The other two are only dispatched when you call start() or stop() on the application context, so you wouldn't want to use those.
If you're using Spring Boot, you may want to look at Spring Boot's
own abstraction of logging systems (org.springframework.boot.logging.LoggingSystem), which defines beforeInitialize, initalize, and cleanUp methods, and also a shutdownHandler that is called when the JVM exists.
And see org.springframework.boot.context.logging.LoggingApplicationListener for reference. Spring Boot comes with additional application events. The initialization of the logging system seems to be done on the ApplicationEnvironmentPreparedEvent. Cleanup is done on ContextClosedEvent and ApplicationFailedEvent.

When is ContextRefreshedEvent fired in Spring?

I know that it is fired once when the ApplicationContext is fully loaded, but what about after that during runtime? The word "Refreshed" implies that it will be triggered on a refresh but I wonder what Spring qualifies as an ApplicationContext refresh?
Followup question:
Can this event be triggered by concurrent threads? Do I need to make the EventHandler for this event thread safe?
it is fired when properties, xml or any schema files are loaded/refreshed, http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/AbstractApplicationContext.html#refresh--
Load or refresh the persistent representation of the configuration,
which might an XML file, properties file, or relational database
schema.
It is fired implicitly by spring usually, but you should be able to fire that on certain instances, But here is java doc says when that happens
As this is a startup method, it should destroy already created
singletons if it fails, to avoid dangling resources. In other words,
after invocation of that method, either all or no singletons at all
should be instantiated.

Application context getting initialized twice

I'm new to Spring and have inherited some Groovy code that relies heavily on Spring. I'm now trying to figure out why my application context is getting intialized twice, and causing multiple copies of my beans to be created.
I've added a #Scheduled task that gets executed with a ThreadPoolTaskExecutor, and inside the task I'm using the application context's getBean static method. In the main program, I'm also using the context to get beans, and I'm finding that the context is getting initialized in both the main program and the scheduled task, which means the task is using a different copy of the bean than the rest of the program.
Ugh, never mind. I was creating two different ApplicationContext objects, both loading the same Config. So problem solved.

Using Spring AOP with Quartz scheduler

I am using Quartz scheduler for scheduling purposes in my project. I need to gather statistics like when, for how long, and how many times a job was run. I want to use Spring AOP for the same. For this, I am making Job classes spring-managed beans. Spring creates a Proxy class for each of the Job classes. But now when Quartz tries to execute this spring-managed Job, I am getting InstantiationException for the Proxy class created for the Job by Spring.
org.quartz.SchedulerException: Problem instantiating class '$Proxy6'
[See nested exception: java.lang.InstantiationException: $Proxy6]
Can anybody please suggest a solution for this problem?
If you use quarz directly (not via Spring Schedule annotation), you can ask quarz directly for the statistics. -- Many of them are already implemented in quarz.
Because Quartz Job class is managed by Quartz container not Spring container, Spring AOP can not achieve your goal. For your purpose, there are 2 ways that you can work on this:
Quartz has listener mechanism builtin, you can use a global listener to do want you want, as the AOP works. For more information about listener, refer to: Quartz document.
If you insist on Spring AOP, you have to customize the job class instantiation process, so that the job class is managed by Spring Container. One approach is write your own JobFactory, which extends SpringBeanJobFactory then override the createJobInstance() method. If you want more things about this, please comment on this, I will write more detail on this.

Resources