views:

1091

answers:

6

Upon starting my webapp within Tomcat 6.0.18, I bootstrap Spring with only what is necessary to initialize the system -- namely, for now, database migrations. I do not want any part of the system to load until the migrations have successfully completed. This prevents the other beans from having to wait on the migrations to complete before operating, or even instantiating.

I have a startup-appcontext.xml configured with a dbMigrationDAO, a startupManager which is a ThreadPoolExecutor, and lastly, a FullSystemLauch bean. I pass a list of configuration locations to the FullSystemLaunch bean via setter injection. The FullSystemLaunch bean implements ServletContextAware, gets a reference to the current WebApplicationContext and thus I can have a ConfigurableListableBeanFactory. Unfortunately, this bean factory isConfigurationFrozen() returns true, so by calling beanFactory.setConfigLocations(configLocations) has no effect.

Can I accomplish this or is Spring preventing me from doing so because it's a bit out of the ordinary? It seems reasonable if understood, but also a bit dangerous. And yes, I'm willing to blow away the current context b/c the currently loaded Singletons are not needed once initialization is complete.

Thank you for the help.

+2  A: 

You could use the existing context as parent context for the other contexts, although I doubt that you could replace the existing WebApplicationContext.

If you use EAR - WAR packaging, you get this out-of-the-box (sort of) by loading an application context from the EAR and then adding one in the WAR.

Not sure whether this is applicable in your situation.

Maarten Winkels
A: 

Could lazy-initialization be an alternative for what you are trying to achieve?

kgiannakakis
No; there would still have to be logic in each of the beans to prevent it from either instantiating or "doing its work" before the system is initialized.
Elliot
Why not just set all beans to be lazy. Then create a holder bean, also lazy-initialized and add all the other beans as dependencies. When you call beanContext.getBean("mybean") all beans will be instantiated.
kgiannakakis
A: 

Possible XmlBeanDefinitionReader can help you?

FoxyBOA
+2  A: 

My opinion would be to allow Spring to initialise your beans is it sees fit - in the order of their declared dependencies.

If you need database migrations there are a couple of patterns to have them run first:

  • if you're using Hibernate/JPA make your sessionFactory/persistenceManager depend-on the migration beans;
  • if you're using plain JDBC create a wrapper DataSource and in its init-method invoke the migrations ( code sample)

The advantage is clear: simplicity.

Robert Munteanu
A: 

you can upcat the WebApplicatonContext to ConfigurableWebApplicationContext then use the setConfigurations method.

dont forget refresh;

constantine
A: 

There was the same task and I created two contexts: startUpContext.xml and applicationContext.xml. In startUpContext.xml there is a bean, which triggers loading of appliationContext.xml. (application context location is configured in startUpContext.xml as a property of a trigger). And finally the trigger replaces locations of the current context and refreshes it:

applicationContext.setConfigLocations(locations);
applicationContext.refresh();

(startUpContext.xml is loaded with a standard spring context loader listener)

serge_bg