I have a Spring Web application with an applicationContext.xml loaded through a ContextLoaderListener in an XmlWebApplicationContext. The application context has a Quartz scheduler (defined with a SchedulerFactoryBean like here) but has no trigger nor job details.
During loading of this main application context, I load some "plug-in" JARs containing their own pluginApplicationContext.xml file.
Each pluginApplicationContext.xml is loaded in a GenericXmlApplicationContext as a child of the main XmlWebApplicationContext.
Those plug-ins may contain Quartz jobs (QuartzJobBean) which are scheduled within the scheduler discussed above. Scheduling have to be done programmatically through the Quartz API but this is fine for me. When the job is triggered, it is well instanciated by Quartz and, because it extends the QuartzJobBean, I'm able to get the current ApplicationContext through setApplicationContext.
The problem here is that I get the XmlWebApplicationContext instead of the GenericXmlApplicationContext from which the job have been scheduled. Thus, I cannot call getBean to retrieve the beans defined within the plugin.
I well understand why all of this happen. But I cannot find a clean and reusable solution to handle it. I've already had a look at OSGi but we're implementing this plug-in system on an existing application, not creating a new one from scratch and migrating the whole application to OSGi would be too much work to do. Do you know how OSGi and other plug-in frameworks deal with this kind of situation?
Thanks a lot for your help
I am not sure I get all those spring problems but I've done these things with OSGi.
What people often do not realize is that you can embed OSGi in your existing application without making any changes to the existing code. Richard Hall describes it here http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html (the API is 100% standardized).
Having a framework, you can then run your plugins in the framework. You will have to make sure the framework exports all the application packages (see the org.osgi.framework.system.packages.extra launch property). Plugins and application can then communicate through services.
I've never used Quartz but I've some experience with scheduling. I register a Runnable service with cron like properties:
#Component(properties="cron=1 * * * *")
public void SomeImpl implements Runnable {
public void run() {
...
}
}
You will then need to make a bundle that calls that service according to its cron specification).
I agree osgi is a good approach, but maybe you can simply crate one huge application context (to rule them all)? Instead of manually starting new child application context based on pluginApplicationContext.xml file simply add:
<import resource="classpath:/pluginApplicationContext.xml"/>
And this will find all plugins and merge their beans into a single application context. From architecture point of view this is a worse approach, but it will work if you discover all plugins at startup time.
Related
Annotated spring beans in my spring-cloud application are being created twice. I assume this is because they get constructed into the bootstrap context and then into a child application context.
For me this is undesirable because some are annotated with #Scheduled to perform periodic refreshes of the data that they provide from a backend data source and this is happening twice in quick succession once for each context.
If it's not otherwise harmful then can I disable all of the application beans from being created in the bootstrap context? If not then can I detect in code when I'm running in the bootstrap context? I use entirely annotation-based beans with component scanning enabled on the Camden SR4 release.
OK I solved this myself. It was down to two different issues in the code and nothing to do with multiple contexts.
Firstly my long held assumption that an #PostConstruct method is only ever called once was false. Moving my one-off bean initialisation code to an implementation of ApplicationListener<ApplicationReadyEvent> solved that one.
Secondly I got bit by multiple initialisation of a bean with an #Scheduled annotation causes the scheduler to run multiple times. To be fair, this behaviour is noted in the documentation. This was easily solved by moving the scheduled task creation to a regular java ScheduledExecutorService set up in the ApplicationReadyEvent implementation.
I'm trying out Quartz scheduler and managed to get it to work with Spring using Maven.
What I need to do is configure Quartz to store the jobs so that for a scheduled time it may execute the job. As far as I know there are two types of triggers in Quartz, Simple and Cron. And I also found out that there is something called JobStore in Quartz. I got it configured to some extent.
Could someone please give me a good reference/references on how to setup Quartz, JobStore? Big help, thank you.
You can have a look at these links
Quartz JobStore with Spring Framework
http://trimplement.com/using-spring-and-quartz-with-jobstore-properties/
If you still cant figure it out then let me know
Just to give you another option, have you try task scheduling of Spring?. Nowadays I change all my old Quartz jobs for this and is easier to configure and you can use the annotations.
http://spring.io/blog/2010/01/05/task-scheduling-simplifications-in-spring-3-0/
You will usually create a Scheduler from a factory class. Quartz can be setup in several ways.
By using the org.quartz.impl.StdSchedulerFactory.getDefaultScheduler(). This will load the quartz.properties file in the Quartz distribution if you have not provided your own.
By specifying your configuration as Key-Value pairs in a quartz.properties file and loading it in org.quartz.impl.StdSchedulerFactory(java.lang.String fileName).getScheduler().
By specifying your configuration in a java.util.Properties as Key-Value pairs and loading it in org.quartz.impl.StdSchedulerFactory(java.util.Properties props).getScheduler().
By using the spring-context-support jar from the Spring Framework and using a higher level abstraction such as org.springframework.scheduling.quartz.SchedulerFactoryBean.
etc.
Quartz will start triggering jobs only when the org.quartz.Scheduler#start() has been invoked. Until this method is called the Scheduler will be in Standby mode.
The Scheduler can be destroyed to release threads by calling org.quartz.Scheduler#shutdown().
Example of Bootstrapping Quartz with Spring
#org.springframework.context.annotation.Configuration
public class QuartzExample {
...
#org.springframework.context.annotation.Bean
public org.springframework.scheduling.quartz.SchedulerFactoryBean schedulerFactory() {
org.springframework.scheduling.quartz.SchedulerFactoryBean factoryBean = new org.springframework.scheduling.quartz.SchedulerFactoryBean();
return factoryBean;
}
}
The bean definition above is enough to perform the following configuration:-
JobFactory - The default is Spring’s org.springframework.scheduling.quartz.AdaptableJobFactory, which supports java.lang.Runnable objects as well as standard Quartz org.quartz.Job instances.
ThreadPool - Default is a Quartz org.quartz.simpl.SimpleThreadPool with a pool size of 10. This is configured through the corresponding Quartz properties.
SchedulerFactory - The default used here is the org.quartz.impl.StdSchedulerFactory, reading in the standard quartz.properties from quartz.jar.
JobStore - The default used is org.quartz.simpl.RAMJobStore which does not support persistence and is not clustered.
Life-Cycle - The org.springframework.scheduling.quartz.SchedulerFactoryBean implements org.springframework.context.SmartLifecycle and org.springframework.beans.factory.DisposableBean which means the life-cycle of the scheduler is managed by the Spring container. The org.quartz.Scheduler#start() is called in the start() implementation of SmartLifecycle after initialization and the org.quartz.Scheduler#shutdown() is called in the destroy() implementation of DisposableBean at application teardown.
You can override the startup behaviour by setting org.springframework.scheduling.quartz.SchedulerFactoryBean().setAutoStartup(false). With this setting you have to manually start the scheduler.
All these default settings can be overridden by the calling the various setter methods on org.springframework.scheduling.quartz.SchedulerFactoryBean.
I have provided a full working example on Github. If you are interested in an example that saves the jobs in a database checkout the HSQLDB branch of the same repository.
I am implementing a web application using Spring. I am using Spring's ContextLoaderListener, to load up my application contexts, and Spring's DispatcherServlet, to load the relevant beans from {name}-servlet.xml, which refer to the beans in the main application context. I want to be able to integration test these Spring configurations outside of the container to validate everything is wired up correctly before I deploy to Tomcat. However my application requires some scheduled background processing when running in the container. In a regular HttpServlet I would simply implement init() and destroy(). All the suggestions I have read suggest using an InitializingBean for that kind of initialization.
However, if I use an InitializingBean, afterPropertiesSet() gets called whether I am inside the container or in integration tests - and outside the container, I don't have access to the resources that background task needs. Is there a better way to perform the tasks I would normally perform in init() and destroy() so that they will only run when deployed as a webapp?
Have you considered using a test spring config file that overrides the bean implementing your background process?
This way everything else in the spring configuration would work normally except for the one overridden bean.
I'm attempting to create a Spring application (NOT web application) to perform some simple tasks. Eventually they will hook up with some other Spring apps around the network, but for now I'm keeping it simple. I have a CheckForNewItems class (extending Timer) which is configured to run every 10 seconds.
I can confirm it runs by calling it programmatically:
public class Tester {
public static ApplicationContext context;
private void loadContext() {
String filename = "beans.xml";
context = new FileSystemXmlApplicationContext(filename);
}
public static void main(String[] args) {
Tester test = new Tester();
test.loadContext();
CheckNewItemsTask task = (CheckNewItemsTask)context.getBean("checkNewItemsTask");
}
}
Running this works as expected, task.run() gets called every 10 seconds. Now I need to work out how to deploy this to either a JBoss or Tomcat server, in such a way that it automatically starts running the task.
Most of the tutorials I've found only describe how to get Spring MVC and servlets running, not a standalone application. Does anyone know better?
Cheers, Rob.
You don't need JBoss or Tomcat to do that. If the app is headless and you have no intention of adding a UI, consider jsvc for unix or procrun on windows. If you need the ability to monitor and control an app and do not need a proper UI for doing that, you might want to look at JMX. This will work on a daemon without the rest of the Java EE stack.
If you have a maven project and want an easy way to turn it into a deployable daemon app, you can use maven appassembler to automate the process of creating a deployable daemon, setting up a directory structure of the app, scripts to start and stop, libraries and config files.
You need a servlet that is set to autostart on deployment. The servlet can then call into your "Tester" class to trigger your "standalone" initialization process.
If you don't have a servlet (or potentially some other server related process) reference your code, then your initialization process will never be run.
I am planning an application that must provide services that are very much like those of a Java EE container to third party extension code. Basically, what this app does is find a set of work items (currently, the plan is to use Hibernate) and dispatch them to work item consumers.
The work item consumers load the item details, invoke third party extension code, and then if the third party code did not fail, update some state on the work item and commit all work done.
I am explicitly not writing this as a Java EE application. Essentially, my application must provide many of the services of a container, however; it must provide transaction management, connection pooling and management, and a certain amount of deployment support. How do I either A) provide these directly, or B) choose a third party library to provide them. Due to a requirement of the larger project, the extension writers will be using Hibernate, if that makes any difference.
It's worth noting that, of all of the features I've mentioned, the one I know least about is transaction management. How can I provide this service to extension code running in my container?
Hi I recommend using the Spring Framework. It provides a nice way to bring together a lot of the various services you are talking about.
For instance to address your specific needs:
Transaction Management/Connection pooling
I built a spring-based stand-alone application that used Apache commons connection pooling. Also I believe spring has some kind of transaction mgmt built in.
Deployment support
I use ant to deploy and run things as a front-loader. It works pretty well. I just fork a seperate process using ant to run my Spring stand-alone app.
Threading.
Spring has support for Quartz which deals well with threads and thread pools
DAO
Spring integrates nicely with Hibernate and other similar projects
Configuration
Using its xml property definitions -- Spring is pretty good for multiple-environment configuration.
Spring does have transaction management. You can define a DataSource in your application context using Apache DBCP (using a org.apache.commons.dbcp.BasicDataSourceorg.springframework.jdbc.datasource.DataSourceTransactionManager for the DataSource. After that, any object in your application can define its own transactions programatically if you pass it the TransactionManager, or you can use AOP interceptors on the object's definition in your application context, to define which methods need to be run inside a transaction.
Or, the easier approach nowadays with Spring is to use the #Transactional annotation in any method that needs to be run inside a transaction, and to add something like this to your application context (assuming your transactionManager is named txManager):
<tx:annotation-driven transaction-manager="txManager"/>
This way your application will easily accept new components later on, which can have transaction management simply by using the #Transactional annotation or by directly creating transactions through a PlatformTransactionManager that they will receive through a setter (so you can pass it when you define the object in your app context).
You could try Atomikos TransactionsEssentials for Java transaction management and connection pooling (JDBC+JMS) in a J2SE environment. No need for any appservers, and it is much more fun to work with ;-)
HTH
Guy