PDA

View Full Version : lazy-init ignored for singleton bean



kkt
Oct 11th, 2006, 01:50 PM
Hi all,

It seems like the lazy-init attribute on a singleton bean is ignored when the org.springframework.jmx.export.MBeanExporter is used to expose it as a MBean. I've added an init-method for the singleton bean but it is called during start-up if it is exposed as MBean. I thought this is not suppose to happen as lazy-init should be honored according to the documentation. Is this a configuration issue?

Thanks.

wpoitras
Oct 11th, 2006, 02:12 PM
Is the bean used by any other bean or retrieved from the bean factory somewhere else? Perhaps you should turn on debugging information to make sure the object is being lazy initialized. Does the object have any interfaces? If not perhaps CGLIB is required to proxy the object for lazy initialization.

kkt
Oct 11th, 2006, 02:17 PM
This bean works as expected if not exposed as MBean. That is, the init method is called only after the bean is referenced. However, if the bean is exposed as MBean, the init method is called when the appliction context is created. Currently, the bean has two interfances.

wpoitras
Oct 11th, 2006, 02:35 PM
Can you set a breakpoint in your init method? Perhaps your JMX server is scanning all of its beans at startup, which would instantiate the bean.

Other than that I can't think of anything. What version of Spring are you using? I've looked at the 1.2.8 version of MBeanExporter and looks like its doing the right thing.

kkt
Oct 12th, 2006, 12:54 AM
This is the stacktrace at the time the initialize() function is called:

TestService.initialize() line: 10
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available
Method.invoke(Object, Object...) line: not available
DefaultListableBeanFactory(AbstractAutowireCapable BeanFactory).invokeCustomInitMethod(String, Object, String, boolean) line: 999
DefaultListableBeanFactory(AbstractAutowireCapable BeanFactory).invokeInitMethods(String, Object, RootBeanDefinition) line: 961
DefaultListableBeanFactory(AbstractAutowireCapable BeanFactory).initializeBean(String, Object, RootBeanDefinition) line: 924
DefaultListableBeanFactory(AbstractAutowireCapable BeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 415
AbstractBeanFactory$1.getObject() line: 245
DefaultListableBeanFactory(DefaultSingletonBeanReg istry).getSingleton(String, ObjectFactory) line: 141
DefaultListableBeanFactory(AbstractBeanFactory).ge tBean(String, Class, Object[]) line: 242
DefaultListableBeanFactory(AbstractBeanFactory).ge tBean(String) line: 156
BeanDefinitionValueResolver.resolveReference(Strin g, RuntimeBeanReference) line: 246
BeanDefinitionValueResolver.resolveValueIfNecessar y(String, Object) line: 128
BeanDefinitionValueResolver.resolveManagedMap(Stri ng, Map) line: 299
BeanDefinitionValueResolver.resolveValueIfNecessar y(String, Object) line: 140
DefaultListableBeanFactory(AbstractAutowireCapable BeanFactory).applyPropertyValues(String, RootBeanDefinition, BeanWrapper, PropertyValues) line: 850
DefaultListableBeanFactory(AbstractAutowireCapable BeanFactory).populateBean(String, RootBeanDefinition, BeanWrapper) line: 624
DefaultListableBeanFactory(AbstractAutowireCapable BeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 411
AbstractBeanFactory$1.getObject() line: 245
DefaultListableBeanFactory(DefaultSingletonBeanReg istry).getSingleton(String, ObjectFactory) line: 141
DefaultListableBeanFactory(AbstractBeanFactory).ge tBean(String, Class, Object[]) line: 242DefaultListableBeanFactory(AbstractBeanFactory) .getBean(String) line: 156
DefaultListableBeanFactory.preInstantiateSingleton s() line: 304
ClassPathXmlApplicationContext(AbstractApplication Context).refresh() line: 348
ClassPathXmlApplicationContext.<init>(String[], ApplicationContext) line: 92
ClassPathXmlApplicationContext.<init>(String[]) line: 77
ClassPathXmlApplicationContext.<init>(String) line: 68
Main.main(String[]) line: 11

with the following Spring configuration file (test.xml):

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
default-init-method="initialize" default-destroy-method="shutdown" default-lazy-init="true" default-autowire="no">

<bean id="testService" class = "TestService" lazy-init="true">
<property name="foo" value="100"/>
</bean>

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=testService">
<ref bean="testService"/>
</entry>
</map>
</property>
</bean>
</beans>

I am using Spring-2.0 RC4 and running Java 1.5 standalone with -Dcom.sun.management.jmxremote

wpoitras
Oct 12th, 2006, 07:35 AM
You need to use beanNames when referring to objects. According to the MBeanExporter#setBeans javadoc:

Bean names will be resolved as beans in the current factory, respecting lazy-init markers (that is, not triggering initialization of such beans).

To fix this change:


<map>
<entry key="bean:name=testService">
<ref bean="testService"/>
</entry>
</map>

To:

<map>
<entry key="bean:name=testService">
<idref local="testService"/>
</entry>
</map>

This is because the map reference to a bean automatically instantiates it. This is done before the MBeanExporter does it magic with lazy-init.

kkt
Oct 12th, 2006, 12:10 PM
Thanks Bill. That did it and is working as expected.