I think this should already be taken care by Spring.
JBossSpringDeployer doesn't have anything to do with beans lifecycle, except from instantiating/destroying AppContext/BeanFactory.
The only reason I could think of is that you're using SpringBeanFactoryDeployer which only creates BeanFactory instance, not ApplicationContext instance.
AFAIK it's only AppContext impl that handles init/destroy, but I could be wrong.
But I don't think the destroy methods of the beans are invoked (added some log messages but they didn't show up in the log).
Which log level did you use?
Try throwing some exception just to make sure. :-)
I checked the mbean defined in the spring deployer and it is using SpringApplicationContextDeployer. Then I threw an exception inside one of the bean's destroy method and it showed up, so after all the destroy method is being called, just that I didn't set up my log correctly. Thanks for the pointers!
Then I noticed the deployed app is registered in JNDI, so I went further to deploy two spring apps (app1 and app2), where in app2 I refer to the app1's context using jndi, like this in app2's applicationContext.xml:
<bean id="app1Context" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="app1"/> <property name="expectedType" value="org.springframework.context.support.AbstractApplicationContext"/> </bean>
The issue is, when I shutdown jboss, I see the message "Failed to stop bean factory app2", and if I remove this bean, the app can be undeployed without failing. It also works if I make this bean prototype scope instead of a singleton. Is there a downside for making this a prototype bean?
Is there a downside for making this a prototype bean?
This is more of a Spring question, so you should really ask there.
But I think this is what happens here is that if a bean is prototype, Spring doesn't track it anymore, so nothing happens on shutdown - since it's out of Spring's scope.
What you should really use is, SpringDeployer's hierarchy notion:
Since we'd like to hot deploy many different Spring archives, each of them must be uniquely represented in our environment. For that purpose, JNDI will be used as a registry for these deployments. But where can we get our local JNDI name? By default, this JNDI name is obtained from the archive's file name: <name>.spring or <name>-spring.xml. But since it's also possible for each bean factory to have parent bean factory, there should be a way to define this parent's name too. This can be done in Spring's beans xml descriptor in description tag as shown in Listing 3.
We are parsing this description tag and looking for a regular expression pattern of 'BeanFactory=(<name>)' and 'ParentBeanFactory=(<name>)' so see Listing 4.
Every time a Spring component is undeployed, we get the corresponding Bean factory through the URL string key in our bean factory map. We remove the map entry, destroy the bean factory singletons, and unbind it from JNDI. When undeploying components be careful of the bean factory hierarchy; don't undeploy some other component's parent bean factory. When shutting down, JBossAS undeploys components in reverse order, which is the right behavior for our child-parent bean factory hierarchy.
And then you can access other context's bean directly.