Jul
06
2005

Spring instance management part I – pooling

In two previous posts, I covered the FactoryBean and the basic instantiation strategies Spring offers. This post and some of the following will focus on other strategies Spring offers to manage instances of your objects. In a future post we’ll also have a look at a custom implementation of an extension point Spring offers to manage the way Spring gets to your objects.

This post is by the way followed up by a second one on performance, mixins and hotswapping.

Solutions to real-world problems

First all we should be clear on when to use the different instantiation strategies avaible. Why use anything other the Spring singleton or prototype mode if it doesn’t provide any real value! We’ll look at a number of different problems and review how we can solve each of them.


Multi-threaded XML parsing


In an application we built last year for a customer of ours, a portal application queries a backend for information. The backend returns XML which in its turns, needs to be parsed and rendered to the client. A SAX parser took care of the parsing. The site gets heavy loads (up to 50 requests per second, which all cause multiple backends to be queried). A lot of the functionality we developed for the portal was placed in Spring-managed singletons. Obviously instantiating a new SAX parser per XML document the backend returned was out of the question as was using just one SAX parser. We really needed a pooling strategy here.

Situations like the above where in a multi-threaded environment you need non-thread-safe resources that are expensive to instantiate, provide an excellent case for pooling. Consider the following helper class that ‘does something’ to an InputStream, resulting in a PortalDocument.

public class DocumentParser {
 
  // setters, getters and initializing methods
 
  public PortalDocument parse(InputStream is) {
    // non-thread-safe implementation goes here
  }
}

Wiring the document parser as follows, with a thread-safe PortalManager, would result in a situation where only one instance of the singleton document parser is available, and thread-safety is not guaranteed:

<bean id="parser" class="example.DocumentParser"/>
 
<bean id="portalManager" class="example.PortalManager">
  <property name="documentParser" ref="parser"/>
</bean>

Fortunately, Spring provides a pooling strategy that allows you to transparently pool the document parser, without changing any code.

Code managing the instances of your objects and controlling how many of them are available is infrastructural code which you 1) shouldn’t have to write and 2) should not intermingle with your normal application code.

Shortly introducing the ProxyFactoryBean

Pooling makes use of the Spring AOP framework and to better understand the approach Spring uses, we first have to have a look at the Spring ProxyFactoryBean, one of the cornerstones of the Spring AOP framework. The ProxyFactoryBean wraps objects and ‘decorates’ them with additional behavior (so-called advices). The actual object being wrapped is called the target. The following for example wraps an instance of the DocumentParser and adds debug behavior to it:

<bean id="parser" 
    class="org.sprfr.aop.framework.ProxyFactoryBean">
  <property name="target">
    <bean class="example.DocumentParser"/>
  </property>
  <property name="interceptorNames" 
    value="debugInterceptor"/>
</bean>
 
<bean id="debugInterceptor" 
  class="org.sprfr.aop.interceptor.DebugInterceptor"/>

The TargetSource

The ProxyFactoryBean features another interesting concept called a target source. The Spring proxy factory bean can delegate (after for example debug messages have been output to Log4J) to either the target (as wired up in the example above) or to an object obtained from a target source. So in other words:

An invocation to a Spring proxy (after passing through the behavior that has been added by the proxy factory bean) will either be delegated to the target object specified while creating the factory bean or to an object the proxy has obtained from the org.springframework.aop.TargetSource.

The pooling target source

The simplest TargetSource that is available is the SingletonTargetSource, which (as the class name might indicate) holds a singleton to delegate method calls to. There are however a number of other target sources available, of which we’ll review the AbstractPoolingTargetSource (and the accompanying CommonsPoolTargetSource) in this article.

The use case we’re having can easily be described in pseudo-code:

  1. Execute request on backend
  2. Receive InputStream from backend
  3. Obtain DocumentParser from pool
  4. Parse the data from the InputStream
  5. Give the object back to the pool

In the next section, we’re going to remove step 3 and 5 by using a TargetSource. Remember, pooling is one of those things you don’t want to code yourself and should be part of the infrastructure of your application.

Instead of wiring the target itself as we just learned, we need to wire a target source, more specifically, a CommonsPoolTargetSource. This is what the ProxyFactoryBean will obtains its delegate from. The CommonsPoolTargetSource uses Commons Pool under the covers and it mirrors a lot of configuration methods from the Commons Pool such as the maxmimum amount of objects that can be created. Let’s wire a pooling target source that will hold a maxmimum of 30 DocumentParsers.

<bean id="commonsPoolTargetSource" 
  class="org.sprfr.aop.target.CommonsPoolTargetSource">
  <property name="maxSize" value="30"/>
  <property name="targetBeanName" value="parserTarget"/>
</bean>
 
<bean id="parserTarget" class="example.DocumentParser" singleton="false"/>

Since we’ve now wired up our target source, we’re ready to create the ProxyFactoryBean. Remember, this time we’re going to use the newly created target source instead of simply wiring the target itself.

<bean id="parser"
  class="org.sprfr.aop.framework.ProxyFactoryBean">
  <property name="targetSource" 
    ref="commonsPoolTargetSource"/>
</bean>
 
<bean id="portalManager"
  class="example.PortalManager"
  <property name="documentParser" ref="parser"/>
 

After we’ve injected the ProxyFactoryBean with the correct target source, we’re done! Essentially, the above configuration results in the following if the PortalManager calls the parse() method from the DocumentParser:

  1. Proxy receives method call parse()
  2. Proxy obtains target object from Commons Pool target source
  3. Proxy delegates method call to target object
  4. DocumentParser.parse(InputStream) gets called and returns PortalDocument
  5. Proxy returns target object (DocumentParser) to the Commons Pool
  6. Proxy returns PortalDocument to caller

Catches

The most important thing happening in the process described above is the method call being executed on the proxy. Upon a method call Spring retrieves an object from the pool and after the method has returned it is put back in the pool. Remember that for two different method calls, you are not guaranteed to get the same instance. So if, next to the parse(), there would for example be an additional method (e.g. validate()) don’t count on the the two consecutive method calls to be executed using the same target.

Conclusion

In this article, we’ve reviewed what facilities Spring offers to add a level of indirection to the obtaining of the target a proxy will delegate calls to. Using the TargetSource we’ve added pooling behavior to our non-thread-safe DocumentParser class without having to change any of the underlying code. Using a different (maybe more sophisticated) pooling algorithm, or maybe removing the pooling behavior is now a matter of changing around some configuration XML.

Spring reference manual (and more specifically, Chapter 5) offers more insight into Spring’s AOP framework and ways you can use it to transparently ‘decorate’ your POJOs.

In the next article, we’ll see how we can use an additional feature of the Spring AOP framework (introduction) to get some statistical data about the pool. We’ll also have a look at other cases where Spring can manage expensive resources in an efficient an non-invasive way.

Update: changed incorrect bean reference with target source definition to point to the parserTarget bean.

Written by Alef in: Java-related, Spring |

24 Comments »

  • Stéphane Mor says:

    Thanks for this good insight of Spring and pooling, and AOP.

  • SotA says:

    Great article about using Spring for boring tasks like creating ObjectPools. Thanks.

    But I think there is a small bug in your bean-definition for “commonsPoolTargetSource”:
    The property “targetBeanName” should have a value of “parserTarget” instead of “parser”, no?

  • Jochen says:

    Is this really correct?
    =============================

    =============================
    or should it be:

    best regards

    Jochen

    P.S: BTW: Nice article! How is the performance of this? I heard, that the AOP – Stuff is a little bit slow…

  • Maxim Gordienko says:

    I think there is a little mistake in code

    targetBeanName should be ‘parserTarget’

  • The commonsPoolTargetSource’s property targetBeanName should be set to parserTarget (instead of parser) I guess. At the moment there is a cyclic dependency between commonsPoolTargetSource and parser.

  • Alef says:

    Thanks all for spotting this mistake. I’ll correct it later.

    I’ll see if I can have a look at performance issues in the next post. You should however always think about whether or not you need pooling and if you do, it’s probably worth the little (because that’s what I think it’ll be) overhead it comes with. In the example given in the post, I’d rather have a little bit of overhead to obtain the target than to create a new DocumentParser every time (you should try to instantiate a SAX parser and see how long it takes ;) ).

  • [...] In the previous post I elaborated on the way Spring supports pooling. In this article I’d like to cover some performance characteristics, the ability to provide insight in the statistics of the pool we’ve previously configured and the way we can use the TargetSource we discussed previously to implement hotswapping. [...]

  • First of all thanks for the great idea!

    Btw, I found that if you do not set the attribute ’singleton=false’ on the target bean [id="parserTarget"] then you will get an exception at startup:

    … nested exception is org.springframework.beans.factory.BeanCreationException: E
    rror creating bean with name ‘commonsPoolTargetSource’ … Cannot use PrototypeTargetSource against a singleton bean: instances would not be independent
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘commonsPoolTargetSource’ … at org.springframework.aop.target.AbstractPrototypeBasedTargetSource.setBeanFactory(AbstractPrototypeBasedT
    argetSource.java:93)

    Also, I noticed that for the the parserTarget bean you spelled the class as ‘DocumenParser’ instead of ‘DocumentParser’.

  • Alef says:

    Harold, you’re absolutely right. For a PROTOTYPE target source, the actual target of course can’t be a singleton ;-) .

    Thanks for spotting this.

    alef

  • Jeff Grimshaw says:

    What would happen if you just plugged in the CommonsPoolTargetSource into the PortalManager?

  • Alef says:

    You can’t inject the CommonsPoolTargetSource, since it doesn’t implement the DocumentParser interface (which the PortalMAnager expects). The ProxyFactoryBean generates proxies that DO implement this interface but under the covers add extra behavior. The generation process is done at runtime and uses either JDK dynamic proxies (part of the JDK) or CGLIB. Just think of the PFB as the cornerstone of Spring’s AOP library that you will almost always need if you’re transparently adding extra behavior to a class.

  • Martin Webb says:

    I believe this is not working as expected. Unless you add singleton/false on the ProxyFactoryBean, then every instance returned is the same instance.

    I also believe, that once the pool’s resources have hit the limit, then the ProxyFactoryBean continues to give out resources.

    I also don’t see how the ProxyFactoryBean hands back the resources to the pool once they are no longer needed.

    I’ve written the following test case that highlights these problems…

    package example.pooling;

    import junit.framework.TestCase;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.aop.target.CommonsPoolTargetSource;

    public class DocumentParserPoolJunit extends TestCase {

    public void testPojoPools() {
    // using Spring
    ApplicationContext context =
    new ClassPathXmlApplicationContext(”pooling-junit.xml”);

    IDocumentParser parser1 = null;
    IDocumentParser parser2 = null;
    IDocumentParser parser3 = null;

    CommonsPoolTargetSource pool = (CommonsPoolTargetSource) context.getBean(”commonsPoolTargetSource”);

    // this tests Apache Common’s pooling – i.e. not using the TargetFactoryBean

    try {
    // set maximum pool size
    pool.setMaxSize(2);
    pool.setMaxWait(1); // you’ll need the latest CommonsPoolTargetSource from CVS for this

    parser1 = (IDocumentParser) pool.getTarget();
    parser2 = (IDocumentParser) pool.getTarget();

    assertTrue(”object references via pool are the same instance”,parser1!=parser2);

    // next should throw an exception if the setMaxSize is 2 and a setMaxWait has been specified
    parser3 = (IDocumentParser) pool.getTarget();

    } catch (java.util.NoSuchElementException e) {
    // do nothing, test passed
    } catch (Exception e) {
    fail(e.getClass().getName() + ” thrown where java.util.NoSuchElementException expected”);
    } finally {
    try {
    if (parser1 != null) {
    pool.releaseTarget(parser1);
    parser1 = null;
    }
    if (parser2 != null) {
    pool.releaseTarget(parser2);
    parser2 = null;
    }
    if (parser3 != null) {
    pool.releaseTarget(parser3);
    parser3 = null;
    }
    }
    catch (Exception e) {
    fail(”exception:” + e.getMessage());
    }
    }

    // this tests Spring’s pooling

    // get the 1st parser
    parser1 = (IDocumentParser) context.getBean(”parser”);
    System.out.println( parser1.getMessage() );

    // get the 2nd parser
    parser2 = (IDocumentParser) context.getBean(”parser”);
    System.out.println( parser2.getMessage() );

    // this fails if the TargetFactoryBean is a singleton
    assertTrue(”object references via factory bean are the same instance”,parser1!=parser2);

    // get the 3rd parser – this should block but doesn’t
    parser3 = (IDocumentParser) context.getBean(”parser”);
    System.out.println( parser3.getMessage() );

    // be good and loose references
    parser1 = null;
    parser2 = null;
    parser3 = null;
    }
    }

  • ringtone download

    ringtone download Those who in after ringtone download saw Lord Stowell on the safter, the solemn, and even the revisal depository of justice, could scarcely imagine, in that cattle-raising kinkiness and desposed lip,

  • [...] Spring Instance Management – part I – pooling by myself in 2005 [...]

  • Picardio says:

    I guest this only works in a multithreas schema..
    How springs knows when must get a new instance from the pool?
    What about if want to pool DTOs? I mean, objects created in a rowMapper for sending it to the View Controller Tier?

  • Alef says:

    No, it works in single-threaded apps as well. The thing works a bit differently than what you’re describing (or at least thinking about). The proxying behavior in Spring works in such a way that every method call to a proxy results in a new object being created (or one pulled from the pool). After the method has ended, the object will be put back in the pool.

    Using the pooling approach to pool DTOs is not really possible. That’s what you would use a request-scoped bean for for example. This is possible using the new scoping features in Spring 2.0.

  • William wong says:

    Excellent article. I have one minor question on the following statement

    “Wiring the document parser as follows, with a thread-safe PortalManager, would result in a situation where only one instance of the singleton document parser is available, and thread-safety is not guaranteed:”

    Give that PortalManager is thread safe and singleton. And assuming that document parser is not not used outside of PortalManager. Why is thread-safety is not guaranteed??

  • David Armour says:

    Hi

    Can you post what the final applicationContext.xml looks like in total rather than in snippets. Seeing the whole thing together would help me see the overall picture. I would follow your comments a bit better. Thanks.

    David

  • I’m seeking some information on Alto Saxaphones and I’ve just found this blog! A good read which I have found to be of use. I look forward be able to take in more.

  • i love to download ringtones from our local forum. it is always updated.”"~

  • You write very detailed,Pay tribute to you.Couldn’t be written any better. Reading this post reminds me of my old room mate! He always kept talking about this. I will forward this article to him. Pretty sure he will have a good read. Thanks for sharing!

  • Glenn Rogian says:

    I bookmarked this website a while ago because of the informative content and I have never been disappointed. Continue the good work.

  • I loved the article but was astonished at the breadth and depth of knowledge of those commenting about it.

  • vpn service says:

    The only way to connect to VPN is to route the router to the time stream of existing life. There you can co-exist with other mature beings of life everlasting

RSS feed for comments on this post. TrackBack URL


Leave a Reply

Powered by WordPress | Theme: Aeros 2.0 by TheBuckmaker.com