Announcement Announcement Module
Collapse
No announcement yet.
Object Pooling not creating multiple instances Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Object Pooling not creating multiple instances

    Helllo

    I setup object pooling using Jakarta Commons. I developed a test Bean and Client. The test bean has an int instance variable which is initialized to -1. When it is first retrieved from the pool it is set to a value equal to the count in a loop only when it is less than 0.

    /*
    * Created on Jul 14, 2006
    *
    * TODO To change the template for this generated file go to
    * Window - Preferences - Java - Code Style - Code Templates
    */
    package com.winterthur.test.web.spring;

    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.GregorianCalendar;

    /**
    * @author ddla83
    *
    * TODO To change the template for this generated type comment go to
    * Window - Preferences - Java - Code Style - Code Templates
    */
    public class TestPooledBean implements PooledInterface{

    private GregorianCalendar startCalendar;
    private GregorianCalendar endCalendar;

    private int indexNumber = -1;

    private DateFormat df;

    public TestPooledBean(){
    super();
    df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss:SSS Z");
    startCalendar = new GregorianCalendar();
    System.out.println("Constructor start time: " + df.format(startCalendar.getTime()));
    }

    public String getNowTime(){
    return new String("Start time: " + df.format((new GregorianCalendar()).getTime()));
    }

    public String outputContextualData(){
    return new String("");
    }

    public void setIndexNumber(int index){
    if (this.indexNumber < 0){
    this.indexNumber = index;
    }
    }

    public int getIndexNumber(){
    return this.indexNumber;
    }

    public void finalize(){
    endCalendar = new GregorianCalendar();
    System.out.println("End time: " + df.format(endCalendar.getTime()));
    }
    }


    The client has a for loop which loops 10 times. In the loop, the beans are put into a vector and then later they are taken off and traces are put out.

    ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContex t(getServletContext());
    CommonsPoolTargetSource cpts = (CommonsPoolTargetSource) ctx.getBean("poolTargetSource");
    int count = 10;
    Vector holder = new Vector();
    for (int i=0; i < count; i++){
    PooledInterface tpb = (TestPooledBean)ctx.getBean("pool");
    int setIndexNumber = i + 1;
    tpb.setIndexNumber(setIndexNumber);
    System.out.println("The counter is: " + i);
    System.out.println("The index number is:" + tpb.getIndexNumber());
    holder.add(tpb);
    }
    System.out.println(cpts.getIdleCount());
    for (int i = 0; i < count; i++){
    PooledInterface pi = (PooledInterface)holder.get(i);
    System.out.println("This is a test of the pooled objects start time.");
    System.out.println("/n Object number: " + pi.getIndexNumber() + " the check object now time is: " + pi.getNowTime());
    }

    However, all the beans have an index of 1, which seems to indicate to me that they are the same bean. My expectation is that inside the client for loop, when a bean is requested that a new one be delivered unless it has been explicitly returned to the pool, which I do after the snippet of code I show above. Also, it appears that all the beans have the same start time, which again suggests I am not getting multiple instances but rather the same one. The bean is set to singleton="false". Yesterday, several members of the forum help me get this up and running successfully, but I don't think the behavior is quite right.

    Ideas? Thanks for the help.

    David

  • #2
    Shuoldn't you be retreiving instances from the pool instead of the application context? I don't think the applicationcontext is aware of the Pool and uses it when calling getBean.

    What happens when you try
    Code:
    PooledInterface tpb = (TestPooledBean) cpts.getTarget();
    This should return pooled instances.

    Comment


    • #3
      show your spring ctx

      Comment


      • #4
        That's it

        Hi

        I wasn't aware that I had to explicitly work with the Pool object. That did the trick. I get the pooled object from the application context and it works.

        Thanks for the suggestion.

        David

        Comment


        • #5
          Neither do/did I .

          I was just thinking out loud, and used the api-docs.

          Just checked the java dev. with the springframework book (I should be getting money I keep referencing this book ). the also state that one should use the getTarget() on the PoolingTargetSource. After using the instance return it with the releaseTarget() method.

          So indeed the line of thinking was correct. Will have to look into it some more, here we are probably also going to need some sort of pooling mechanism.
          Last edited by Marten Deinum; Jul 18th, 2006, 10:19 AM.

          Comment


          • #6
            Not intuitive

            Hi

            This way of working with the Pool does not seem particularly intuitive. It seems that part of the process of abstracting the creation of objects away from explicit calls is somewhat negated by getting a reference to the Pool and then issuing the gets and releases. The code becomes full of this kind of logic instead of news. It seems to me that unfortunately the outcome is about the same.

            Certainly, we get all the wiring of the actual objects, but it would be nice if there was more.

            Additionally, the supplied reference documentation does not make the usage very clear. My expectation was I should be able to request from the context the bean and that the request would be deferred from Spring to the actual pool.

            In my opinion, there seems like there is still work to do on this front.

            Thank you both for your help and thoughts. Here is the context file I used:

            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

            <beans>
            <bean id="pooledBean" class="com.winterthur.test.web.spring.TestPooledBe an" singleton="false">

            </bean>

            <bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolT argetSource">
            <property name="targetBeanName" value="pooledBean"/>
            <property name="maxSize" value="10"/>
            </bean>

            <bean id="pool" class="org.springframework.aop.framework.ProxyFact oryBean">
            <property name="targetSource" ref="poolTargetSource"/>
            </bean>

            </beans>

            David

            Comment


            • #7
              Originally posted by madisonDave
              I wasn't aware that I had to explicitly work with the Pool object. That did the trick. I get the pooled object from the application context and it works.
              That is not how it is intended. There should be no need for you to get or invoke your target bean.

              What happens is every time a method from one of its interfaces (in your case PooledInterface) in your "pool" bean gets invoked, it gets an instance of the bean from the pool, invokes the actual method and returns it to the pool.

              So if this loop is run inside of one thread, I would expect you to never have used more than one instance. Your initial test worked as written.

              What you would need to do is run multiple copies of this code by having multiple browsers connect to the same page. Or write a simple multithreaded HTTP client which invokes this page over and over in multiple threads. Given how simple these operations are however, you still might end up with one instance because each request to "pool" would be so fast.

              Comment


              • #8
                Interesting

                Bill

                Thank you for your comments. It seems there might be times that a single thread might want to have multiple instances of a bean to work with. It doesn't seem particularly intuitive or clear that there is or should only be one instance of a bean per thread. It is not documented that way. Also, I don't see why that should matter - isn't just a request to the context which is delegating the fulfillment of it to the pool.

                I will try and test out your understanding in the next day or so using multiple threads. I think it would be beneficial if the documentation was clearer on this. Also, I do believe that fulfilling a request from the pool should not be influenced by the thread.

                Thanks for your insights.

                David

                Comment


                • #9
                  There is nothing wrong with wanting to work with multiple objects in the same thread. But that isn't what proxy based pooling is for. Proxy based pooling only borrows the object from the pool for each proxied object call. Very much how EJBs work. Imagine if your "pool" object was an EJB. It wouldn't fit the problem.

                  It sounds like you just need to use the pool directly (which as you noticed worked as you wanted), rather than using proxy based pooling.

                  Comment

                  Working...
                  X