I'm doing research on GenericObjectPool
by putting Cipher
in pool so it can be reused.
GenericObjectPool<Cipher> pool;
CipherFactory factory = new CipherFactory();
this.pool = new GenericObjectPool<Cipher>(factory);
pool.setMaxTotal(10);
pool.setBlockWhenExhausted(true);
pool.setMaxWaitMillis(30 * 1000);
CipherFactory
public class CipherFactory extends BasePooledObjectFactory<Cipher> {
private boolean running = false;
@Override
public Cipher create() throws Exception {
return Cipher.getInstance("DESede/CBC/NoPadding");
}
@Override
public PooledObject<Cipher> wrap(Cipher arg0) {
return new DefaultPooledObject<Cipher>(arg0);
}
@Override
public boolean validateObject(PooledObject<Cipher> p) {
//Ensures that the instance is safe to be returned by the pool
return true;
}
@Override
public void destroyObject(PooledObject<Cipher> p) {
//Destroys an instance no longer needed by the pool.
System.out.println("destroying");
}
@Override
public void activateObject(PooledObject<Cipher> p) throws Exception { //Reinitialize an instance to be returned by the pool
setRunning(true);
}
@Override
public void passivateObject(PooledObject<Cipher> p) throws Exception { // reset the object after the object returns to the pool
setRunning(false);
}
public void setRunning(boolean running) {
this.running = running;
}
//
}
This is how I implement ObjectPool
in my Example class
public Key a(byte[] afyte) throws Exception {
Cipher cipher = null;
cipher = pool.borrowObject(); //get the object from the pool
try {
System.out.println("****************** After borrow ****************");
printPool();
cipher.init(Cipher.DECRYPT_MODE, mkkey, algParamSpec);
byte[] de = cipher.doFinal(afyte);
SecretKey mk = new SecretKeySpec(de, "DESede");
return mk;
} catch (Exception e) {
pool.invalidateObject(cipher);
cipher = null;
} finally {
if (null != cipher) {
pool.returnObject(cipher);
System.out.println("****************** After return ****************");
printPool();
}
}
return (Key) cipher;
}
printPool
public void printPool() {
System.out.println("Pool for cipher with instances DESede/CBC/NoPadding");
System.out.println("Active [" + pool.getNumActive() + "]"); //Return the number of instances currently borrowed from this pool
System.out.println("Idle [" + pool.getNumIdle() + "]"); //The number of instances currently idle in this pool
System.out.println("Total Created [" + pool.getCreatedCount() + "]");
}
Am I on the right path ? Is it possible to increase pool size ?
Edit
The answer from @http works fine to me. But if I have another method encryptECB(Key key, byte[] b)
, how should I write ?
Any help would be appreciated !
You are on the right track. When constructing the GenericObjectPool, you can use the constructor that accepts a GenericObjectPoolConfig object which contains all the configuration values for your object pool. The example below would let your pool grow to 20 connections before it was exhausted...
GenericeObjectPoolConfig also has a setBlockWhenExhausted method to specify the behaviour when the pool has reached the maxTotal connections. See https://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/BaseObjectPoolConfig.html#setBlockWhenExhausted-boolean- for details.
A pattern I implement when using commons pool is to create 2 interfaces, one for your pooled object and one for your factory...
CipherFactory implementation...
PooledCipher implementation...
Then you construct your CipherFactory like this...
And use it like this...
Also you can reuse the PooledCipher and CipherFactory interfaces to create other implementations, such as JCA.