chriswberry
Jun 1st, 2005, 12:09 PM
Greetings,
I apologize in advance for the length of this email...
I am writing a simple prototype in anticipation of converting an EJB app to Spring. This EJB app uses object pooling, so I am trying out Spring's object pooling capabilities. Yes, I realize that singletons are generally preferable, but the app owners want their object pooling...
I have followed the example outlined in the online Sping docs. And have the following Beans::
<bean id="myModelTarget"
class="etrade.services.pool.MyModelImpl" singleton="false" >
<property name="outString">
<value>GARBAGE OUT</value>
</property>
</bean>
<bean id="myModelSource"
class="org.springframework.aop.target.CommonsPoolTargetSo urce">
<property name="targetBeanName">
<value>myModelTarget</value>
</property>
<property name="maxSize">
<value>5</value>
</property>
</bean>
<bean id="myModel"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource">
<ref local="myModelSource" />
</property>
</bean>
Where ModelImpl is a very simple class;
public class MyModelImpl implements MyModel
{
static protected org.apache.commons.logging.Log dbglog =
org.apache.commons.logging.LogFactory.getLog( "ETDEBUG." + MyModelImpl.class.getName() );
static private int objKnt = 0;
synchronized static private int nextObjKnt()
{
objKnt++;
return objKnt;
}
private String outString = null;
private int myNum = -1;
public String toString()
{
StringBuffer buff = new StringBuffer();
buff.append( "{ " );
buff.append( super.toString() );
buff.append( " myNum = " + myNum );
buff.append( " }" );
return buff.toString();
}
public MyModelImpl()
{
super();
myNum = nextObjKnt();
dbglog.debug("MyModelImpl CTOR -- created myNum= " + myNum );
}
public String doSomething( String in )
{
dbglog.debug("ENTERED MyModelImpl.doSomething( " + in + " )" );
return in + " ==> " + outString + " " + myNum;
}
public void setOutString( String os )
{ outString = os; }
public String getOutString()
{ return outString; }
}
But when I run the following JUnit:
public void testPoolLimit()
{
List modelPool = new ArrayList();
ApplicationContext context = MyModelDriver.getAppContext();
CommonsPoolTargetSource pool =
((CommonsPoolTargetSource)context.getBean("myModelSource"));
assertTrue(pool.getMaxSize() == 5);
dbglog.debug( "pool.getActiveCount = " + pool.getActiveCount() );
dbglog.debug( "pool.getIdleCount = " + pool.getIdleCount() );
for (int i = 0; i <= 10; i++) {
MyModel model = (MyModel)context.getBean("myModel");
modelPool.add(model);
dbglog.debug( "model = " + model );
dbglog.debug( "pool.getActiveCount = " + pool.getActiveCount() );
dbglog.debug( "pool.getIdleCount = " + pool.getIdleCount() );
}
dbglog.debug( "modelPool.size() = " + modelPool.size() );
//assertTrue(modelPool.size() < 10);
}
I get this output. Note that I seem to get back the same instance every time. Seems to me that I should be getting back different instances since I haven't returned the values to the pool??
...................<snip>
[junit] [06/01/05 09:23:08:937](main )(DefaultListableBeanFactory)[DEBUG]:: Invoking BeanPostProcessors before initialization of bea
n 'myModelTarget'
[junit] [06/01/05 09:23:08:937](main )(DefaultListableBeanFactory)[DEBUG]:: Invoking BeanPostProcessors after initialization of bean
'myModelTarget'
[junit] [06/01/05 09:23:08:937](main )(TestMyModel )[DEBUG]:: model = { etrade.services.pool.MyModelImpl@1d62270 myNum = 2 }
[junit] [06/01/05 09:23:08:937](main )(TestMyModel )[DEBUG]:: pool.getActiveCount = 0
[junit] [06/01/05 09:23:08:937](main )(TestMyModel )[DEBUG]:: pool.getIdleCount = 1
[junit] [06/01/05 09:23:08:957](main )(DefaultListableBeanFactory)[DEBUG]:: Returning cached instance of singleton bean 'myModel'
[junit] [06/01/05 09:23:08:957](main )(DefaultListableBeanFactory)[DEBUG]:: Bean with name 'myModel' is a factory bean
[junit] [06/01/05 09:23:08:957](main )(TestMyModel )[DEBUG]:: model = { etrade.services.pool.MyModelImpl@1d62270 myNum = 2 }
[junit] [06/01/05 09:23:08:957](main )(TestMyModel )[DEBUG]:: pool.getActiveCount = 0
[junit] [06/01/05 09:23:08:957](main )(TestMyModel )[DEBUG]:: pool.getIdleCount = 1
[junit] [06/01/05 09:23:08:986](main )(DefaultListableBeanFactory)[DEBUG]:: Returning cached instance of singleton bean 'myModel'
[junit] [06/01/05 09:23:08:986](main )(DefaultListableBeanFactory)[DEBUG]:: Bean with name 'myModel' is a factory bean
[junit] [06/01/05 09:23:08:986](main )(TestMyModel )[DEBUG]:: model = { etrade.services.pool.MyModelImpl@1d62270 myNum = 2 }
[junit] [06/01/05 09:23:08:986](main )(TestMyModel )[DEBUG]:: pool.getActiveCount = 0
[junit] [06/01/05 09:23:08:986](main )(TestMyModel )[DEBUG]:: pool.getIdleCount = 1
[junit] [06/01/05 09:23:09:6](main )(DefaultListableBeanFactory)[DEBUG]:: Returning cached instance of singleton bean 'myModel'
[junit] [06/01/05 09:23:09:6](main )(DefaultListableBeanFactory)[DEBUG]:: Bean with name 'myModel' is a factory bean
[junit] [06/01/05 09:23:09:6](main )(TestMyModel )[DEBUG]:: model = { etrade.services.pool.MyModelImpl@1d62270 myNum = 2 }
[junit] [06/01/05 09:23:09:6](main )(TestMyModel )[DEBUG]:: pool.getActiveCount = 0
[junit] [06/01/05 09:23:09:6](main )(TestMyModel )[DEBUG]:: pool.getIdleCount = 1
................ <snip>
I did notice this in the output. Do I have this wired wrong??
[junit] [06/01/05 09:23:08:422](main )(DefaultListableBeanFactory)[DEBUG]:: Invoking setBeanFactory on BeanFactoryAware bean 'myMode
l'
[junit] [06/01/05 09:23:08:422](main )(ProxyFactoryBean)[DEBUG]::Not refreshing target: bean name not specified in interceptorNames
It is entirely possible that I am missing something basic. I'm a relative Spring Newbie...
Also, I'm a bit confused. How does Spring release objects back to the pool??
Thanks,
-- Chris
I apologize in advance for the length of this email...
I am writing a simple prototype in anticipation of converting an EJB app to Spring. This EJB app uses object pooling, so I am trying out Spring's object pooling capabilities. Yes, I realize that singletons are generally preferable, but the app owners want their object pooling...
I have followed the example outlined in the online Sping docs. And have the following Beans::
<bean id="myModelTarget"
class="etrade.services.pool.MyModelImpl" singleton="false" >
<property name="outString">
<value>GARBAGE OUT</value>
</property>
</bean>
<bean id="myModelSource"
class="org.springframework.aop.target.CommonsPoolTargetSo urce">
<property name="targetBeanName">
<value>myModelTarget</value>
</property>
<property name="maxSize">
<value>5</value>
</property>
</bean>
<bean id="myModel"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource">
<ref local="myModelSource" />
</property>
</bean>
Where ModelImpl is a very simple class;
public class MyModelImpl implements MyModel
{
static protected org.apache.commons.logging.Log dbglog =
org.apache.commons.logging.LogFactory.getLog( "ETDEBUG." + MyModelImpl.class.getName() );
static private int objKnt = 0;
synchronized static private int nextObjKnt()
{
objKnt++;
return objKnt;
}
private String outString = null;
private int myNum = -1;
public String toString()
{
StringBuffer buff = new StringBuffer();
buff.append( "{ " );
buff.append( super.toString() );
buff.append( " myNum = " + myNum );
buff.append( " }" );
return buff.toString();
}
public MyModelImpl()
{
super();
myNum = nextObjKnt();
dbglog.debug("MyModelImpl CTOR -- created myNum= " + myNum );
}
public String doSomething( String in )
{
dbglog.debug("ENTERED MyModelImpl.doSomething( " + in + " )" );
return in + " ==> " + outString + " " + myNum;
}
public void setOutString( String os )
{ outString = os; }
public String getOutString()
{ return outString; }
}
But when I run the following JUnit:
public void testPoolLimit()
{
List modelPool = new ArrayList();
ApplicationContext context = MyModelDriver.getAppContext();
CommonsPoolTargetSource pool =
((CommonsPoolTargetSource)context.getBean("myModelSource"));
assertTrue(pool.getMaxSize() == 5);
dbglog.debug( "pool.getActiveCount = " + pool.getActiveCount() );
dbglog.debug( "pool.getIdleCount = " + pool.getIdleCount() );
for (int i = 0; i <= 10; i++) {
MyModel model = (MyModel)context.getBean("myModel");
modelPool.add(model);
dbglog.debug( "model = " + model );
dbglog.debug( "pool.getActiveCount = " + pool.getActiveCount() );
dbglog.debug( "pool.getIdleCount = " + pool.getIdleCount() );
}
dbglog.debug( "modelPool.size() = " + modelPool.size() );
//assertTrue(modelPool.size() < 10);
}
I get this output. Note that I seem to get back the same instance every time. Seems to me that I should be getting back different instances since I haven't returned the values to the pool??
...................<snip>
[junit] [06/01/05 09:23:08:937](main )(DefaultListableBeanFactory)[DEBUG]:: Invoking BeanPostProcessors before initialization of bea
n 'myModelTarget'
[junit] [06/01/05 09:23:08:937](main )(DefaultListableBeanFactory)[DEBUG]:: Invoking BeanPostProcessors after initialization of bean
'myModelTarget'
[junit] [06/01/05 09:23:08:937](main )(TestMyModel )[DEBUG]:: model = { etrade.services.pool.MyModelImpl@1d62270 myNum = 2 }
[junit] [06/01/05 09:23:08:937](main )(TestMyModel )[DEBUG]:: pool.getActiveCount = 0
[junit] [06/01/05 09:23:08:937](main )(TestMyModel )[DEBUG]:: pool.getIdleCount = 1
[junit] [06/01/05 09:23:08:957](main )(DefaultListableBeanFactory)[DEBUG]:: Returning cached instance of singleton bean 'myModel'
[junit] [06/01/05 09:23:08:957](main )(DefaultListableBeanFactory)[DEBUG]:: Bean with name 'myModel' is a factory bean
[junit] [06/01/05 09:23:08:957](main )(TestMyModel )[DEBUG]:: model = { etrade.services.pool.MyModelImpl@1d62270 myNum = 2 }
[junit] [06/01/05 09:23:08:957](main )(TestMyModel )[DEBUG]:: pool.getActiveCount = 0
[junit] [06/01/05 09:23:08:957](main )(TestMyModel )[DEBUG]:: pool.getIdleCount = 1
[junit] [06/01/05 09:23:08:986](main )(DefaultListableBeanFactory)[DEBUG]:: Returning cached instance of singleton bean 'myModel'
[junit] [06/01/05 09:23:08:986](main )(DefaultListableBeanFactory)[DEBUG]:: Bean with name 'myModel' is a factory bean
[junit] [06/01/05 09:23:08:986](main )(TestMyModel )[DEBUG]:: model = { etrade.services.pool.MyModelImpl@1d62270 myNum = 2 }
[junit] [06/01/05 09:23:08:986](main )(TestMyModel )[DEBUG]:: pool.getActiveCount = 0
[junit] [06/01/05 09:23:08:986](main )(TestMyModel )[DEBUG]:: pool.getIdleCount = 1
[junit] [06/01/05 09:23:09:6](main )(DefaultListableBeanFactory)[DEBUG]:: Returning cached instance of singleton bean 'myModel'
[junit] [06/01/05 09:23:09:6](main )(DefaultListableBeanFactory)[DEBUG]:: Bean with name 'myModel' is a factory bean
[junit] [06/01/05 09:23:09:6](main )(TestMyModel )[DEBUG]:: model = { etrade.services.pool.MyModelImpl@1d62270 myNum = 2 }
[junit] [06/01/05 09:23:09:6](main )(TestMyModel )[DEBUG]:: pool.getActiveCount = 0
[junit] [06/01/05 09:23:09:6](main )(TestMyModel )[DEBUG]:: pool.getIdleCount = 1
................ <snip>
I did notice this in the output. Do I have this wired wrong??
[junit] [06/01/05 09:23:08:422](main )(DefaultListableBeanFactory)[DEBUG]:: Invoking setBeanFactory on BeanFactoryAware bean 'myMode
l'
[junit] [06/01/05 09:23:08:422](main )(ProxyFactoryBean)[DEBUG]::Not refreshing target: bean name not specified in interceptorNames
It is entirely possible that I am missing something basic. I'm a relative Spring Newbie...
Also, I'm a bit confused. How does Spring release objects back to the pool??
Thanks,
-- Chris