views:

758

answers:

3

We've licensed a commercial product (product not important in this context), which is limited by the number of concurrent users. Users access this product by going through a Spring Controller.

We have N licenses for this product, and if N+1 users access it, they get a nasty error message about needing to buy more licenses. I want to make sure users don't see this message, and would prefer that requests to the product simply "queue up", rather than having N+1 users actually access it. Of course, they would prefer that I purchase the licenses, so their tool won't let us do this natively.

In lieu of being able to control the tool, I'd like to limit the number of concurrent sessions to the controller to never be more than N. Everyone else can wait.

We're using Spring MVC.

Any ideas?

+5  A: 

What you need is a ObjectPool. Check out Apache Commons Pool http://commons.apache.org/pool

At the application startup you should create a Object Pool with licences or objects of commercial library (Not sure what kind of public interface they have).

public class CommercialObjectFactory extends BasePoolableObjectFactory { 
    // for makeObject we'll simply return a new commercial object
    @Override
    public Object makeObject() { 
        return new CommercialObject(); 
    } 
}

GenericObjectPool pool = new GenericObjectPool(new CommercialObjectFactory());

// The size of pool in our case it is N
pool.setMaxActive(N) 
// We want to wait if the pool is exhausted
pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK)

And when you need the commercial object in your code.

CommercialObject obj = null;
try { 
    obj = (CommercialObject)pool.borrowObject();

    // use the commerical object the way you to use it.
    // ....

} finally { 
    // be nice return the borrwed object
    try {
        if(obj != null) {
            pool.returnObject(obj);
        }
    } catch(Exception e) {
        // ignored
    }
}

If this is not what you want then you will need to provide more detail about your commercial library.

TRF
A: 

I'm thinking of a SessionListener to increment the count when a session is created and decrement it when the session is invalidated or times out and an aspect to guard calls to the URL. But a design that clearly marries the two ideas together is eluding me.

duffymo
+1  A: 

Spring has a org.springframework.aop.interceptor.ConcurrencyThrottleInterceptor that can be used via AOP (or the underlying code can be used standalone). That might be a lighter weight approach than using a object pool.

Ed Thomas