Pooling

AEPortal uses a pooling infrastructure that allows various QOS, e.g. aging by time or request count. This infrastructure should be used for all pooling needs.

Note: Pooling is not the same as caching because cached objects need a unique name or id so that clients can address them. This is not necessary for pooling. Still, both could probably be implemented using the same base classes. This would be a topic for the re-design.

Implementation

AEPortal uses a generic object pool called "Minerva". Minerva is now part of the jboss open source project (http://javatree.web.cern.ch/javatree) and does also advanced JDBC connection pooling (JDBC SE, 2 phase commit support) but we only use the generic object pool. It is in the package org.jboss.Minerva.pools. Infrastructure now has a package comaepinfrastructure.pooling which includes standard factories and a main pool factory. This package assumes right now a couple of default pools, e.g. DOMParserPool but new pools can be created programmatically. The process is similar to the creation of new caches: You need a new factory with a method to create a specific object and – optionally – have that object implement the PooledObject interface.

What is missing:

  • a xml description of default pools so that the system can configure the pool factory at boot time (like we do with reference data)

  • a way to do the same at runtime from within applications or services (to make AEPortal dynamically extensible)

  • more quality of service features: aging by time and request.

Documentation: twiki, search for "ObjectPool".

Pooling: why, what and how much?

We pool things because we want to save either time – if it takes a lot of time to build an object – or memory – if an object has a large footprint.

The "what" part is harder to answer: Typically heavyweight objects that are not re-entrant because they keep some state e.g. XML Parsers. Right now it is necessary to give two threads two XML Parser instances because they might each install a different entity manager etc. There is only one requirement: the pooled objects need to be "resettable", i.e. a new client thread (or the pool itself when the object is returned) can return the object to its initial state.

Typically objects that get pooled are:

  • threads

  • database connections

  • XML Parsers

  • Network connections

Pooling: how?

Unlike caching pooling follows an allocate/free pattern. Objects that are not "freed" after use are no longer available for other threads.

Sometimes it is hard to retrofit a piece of code with pooling because the moment where the pooled resource needs to be returned to the pool cannot be determined.

Example 5.2. A pooling example:

	// before pooling
	Class ResourceUser { 
	Public ResourceUser () {
	Resource mResource = new Resource(); // get a new instance
	mResource.setSomeMode(x); // initialize it
	}
	Public useResource() { 
	String result = mResource.parse(foo);
	}
	}
	Given this class, when would you return a pooled resource to the pool?


	// with pooling
	Class ResourceUser { 
	Public ResouceUser () {
	}
	private Resource getResource() {
	Resource mResouce = (Resource) pool.getResource(); // get a pooled instance 
	mResource.setSomeMode(x); // initialize it
	}
	private void freeResource(Resource res) {
	pool.releaseObject(res);
	}
	Public useResource() { 
	Resource res = getResource(); // get resource
	String result = res.parse(foo); // use it 
	FreeResource(res); // return it immediately
	}
	}
		

Note

You can no longer let objects of class PoolUser be collected by the Garbage Collector without returning the pooled resource beforehand. The code is designed for short time usage of a resource. In the non-pooled version the resource is private to class PoolUser. This is expensive but the good side of it is that this cannot create a bottleneck. In the pooled version – if class PoolUser does not call freeResource() after every use – we have created a bottleneck in the system. Of course, if class PoolUser would use the resource in a tight and non-blocking loop, it would probably hold on to the one and avoid the pool management overhead.