User: fleury
Date: 00/10/21 14:32:10
Modified: src/main/org/jboss/ejb/plugins
EntitySynchronizationInterceptor.java
EntityInstanceInterceptor.java
AbstractInstancePool.java
Log:
fix for lock on home exception... the pools notifyAll on free
Revision Changes Path
1.27 +384 -384
jboss/src/main/org/jboss/ejb/plugins/EntitySynchronizationInterceptor.java
Index: EntitySynchronizationInterceptor.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/EntitySynchronizationInterceptor.java,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- EntitySynchronizationInterceptor.java 2000/10/17 23:47:02 1.26
+++ EntitySynchronizationInterceptor.java 2000/10/21 21:32:09 1.27
@@ -48,393 +48,393 @@
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.26 $
+* @version $Revision: 1.27 $
*/
public class EntitySynchronizationInterceptor
extends AbstractInterceptor
{
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
-
- /**
- * The current commit option.
- */
- protected int commitOption;
-
- /**
- * The container of this interceptor.
- */
- protected EntityContainer container;
-
- /**
- * Optional isModified method
- */
- protected Method isModified;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void setContainer(Container container)
- {
- this.container = (EntityContainer)container;
- }
-
- public void init()
- throws Exception
- {
- commitOption =
container.getBeanMetaData().getContainerConfiguration().getCommitOption();
- // Check for isModified method
- try
- {
- isModified = container.getBeanClass().getMethod("isModified",
new Class[0]);
- if (!isModified.getReturnType().equals(Boolean.TYPE))
- isModified = null; // Has to have "boolean" as return
type!
- } catch (Exception e)
- {
- // Ignore
- }
- }
-
- public Container getContainer()
- {
- return container;
- }
-
- /**
- * Register a transaction synchronization callback with a context.
- */
- private void register(EntityEnterpriseContext ctx, Transaction tx)
- {
- // Create a new synchronization
- InstanceSynchronization synch = new InstanceSynchronization(tx, ctx);
-
- try {
- // OSH: An extra check to avoid warning.
- // Can go when we are sure that we no longer get
- // the JTA violation warning.
- if (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) {
-
- ctx.setValid(false);
-
- return;
- }
-
- // We want to be notified when the transaction commits
- tx.registerSynchronization(synch);
-
- } catch (RollbackException e) {
-
- // The state in the instance is to be discarded, we force a
reload of state
- ctx.setValid(false);
-
- } catch (Exception e) {
-
- throw new EJBException(e);
-
- }
- }
-
- private void deregister(EntityEnterpriseContext ctx)
- {
- // MF FIXME: I suspect this is redundant now
- // (won't the pool clean it up?)
-
- // Deassociate ctx with tx
- // OSH: TxInterceptor seems to do this: ctx.setTransaction(null);
- // OSH: Pool seems to do this: ctx.setInvoked(false);
- }
-
- // Interceptor implementation --------------------------------------
-
- public Object invokeHome(MethodInvocation mi)
- throws Exception
- {
- try {
- return getNext().invokeHome(mi);
- } finally {
- // Anonymous was sent in, so if it has an id it was created
- EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
- if (ctx.getId() != null) {
- Transaction tx = mi.getTransaction();
-
- if (tx != null && tx.getStatus() ==
Status.STATUS_ACTIVE)
- register(ctx, tx); // Set tx
-
- // Currently synched with underlying storage
- ctx.setValid(true);
- }
- }
- }
-
- public Object invoke(MethodInvocation mi)
- throws Exception
- {
- // We are going to work with the context a lot
- EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
-
- // The Tx coming as part of the Method Invocation
- Transaction tx = mi.getTransaction();
-
- //Logger.debug("CTX in: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
- //Logger.debug("newTx: "+ tx);
-
- // Is my state valid?
- if (!ctx.isValid()) {
-
- // If not tell the persistence manager to load the state
-
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
-
- // Now the state is valid
- ctx.setValid(true);
- }
-
- // So we can go on with the invocation
- //DEBUG Logger.debug("Tx is "+ ((tx == null)? "null" :
tx.toString()));
-
- // Invocation with a running Transaction
-
- if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE) {
-
- try {
-
- //Invoke down the chain
- return getNext().invoke(mi);
-
- }
-
- finally {
-
- // Do we have a valid bean (not removed)
- if (ctx.getId() != null) {
-
- // If the context was not invoked previously...
- if (!ctx.isInvoked()) {
-
- // It is now and this will cause
ejbStore to be called...
- ctx.setInvoked(true);
-
- // ... on a transaction callback that
we register here.
- register(ctx, tx);
- }
- }
-
- // Entity was removed
- else {
-
- if (ctx.getTransaction() != null) {
-
- //DEBUG Logger.debug("CTX out:
isValid():"+ctx.isValid()+" isInvoked():"+ctx.isInvoked());
- //DEBUG Logger.debug("PresentTx:"+tx);
-
- // If a ctx still has a transaction we
would need to deresgister the sync
- // The simplest is to tell the pool to
kill the instance if tx is present
-
- }
- }
- }
- }
-
- //
- else { // No tx
- try {
- Object result = getNext().invoke(mi);
-
- // Store after each invocation -- not on exception
though, or removal
- // And skip reads too ("get" methods)
- // OSH FIXME: Isn't this startsWith("get")
optimization a violation of
- // the EJB specification? Think of
SequenceBean.getNext().
- if (ctx.getId() != null)
- {
- boolean dirty = true;
- // Check isModified bean flag
- if (isModified != null)
- {
- dirty =
((Boolean)isModified.invoke(ctx.getInstance(), new Object[0])).booleanValue();
- }
-
- // Store entity
- if (dirty)
-
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
- }
-
- return result;
- } catch (Exception e) {
- // Exception - force reload on next call
- ctx.setValid(false);
- throw e;
- }
- }
- }
-
-
- // Protected ----------------------------------------------------
-
- // Inner classes -------------------------------------------------
-
- private class InstanceSynchronization
- implements Synchronization
- {
- /**
- * The transaction we follow.
- */
- private Transaction tx;
-
- /**
- * The context we manage.
- */
- private EntityEnterpriseContext ctx;
-
- /**
- * Create a new instance synchronization instance.
- */
- InstanceSynchronization(Transaction tx, EntityEnterpriseContext ctx)
- {
- this.tx = tx;
- this.ctx = ctx;
- }
-
- // Synchronization implementation -----------------------------
-
- public void beforeCompletion()
- {
- // DEBUG Logger.debug("beforeCompletion called for ctx
"+ctx.hashCode());
-
- if (ctx.getId() != null) {
-
- // This is an independent point of entry. We need to
make sure the
- // thread is associated with the right context class
loader
- ClassLoader oldCl =
Thread.currentThread().getContextClassLoader();
-
Thread.currentThread().setContextClassLoader(container.getClassLoader());
-
- try {
-
- try {
-
- // MF FIXME: should we throw an
exception if lock is present (app error)
- // it would mean that someone is
commiting when all the work is not done
-
- // Store instance if business method
was invoked
- if (ctx.isInvoked()) {
-
- //DEBUG
Logger.debug("EntitySynchronization sync calling store on ctx "+ctx.hashCode());
-
- // Check isModified bean flag
- boolean dirty = true;
- if (isModified != null)
- {
- try
- {
- dirty =
((Boolean)isModified.invoke(ctx.getInstance(), new Object[0])).booleanValue();
- } catch (Exception e)
- {
- // Ignore
-
e.printStackTrace();
- }
- }
-
- if (dirty)
-
container.getPersistenceManager().storeEntity(ctx);
- }
- } catch (NoSuchEntityException e) {
- // Object has been removed -- ignore
- }
- }
- catch (RemoteException e) {
- Logger.exception(e);
-
- // Store failed -> rollback!
- try {
- tx.setRollbackOnly();
- } catch (SystemException ex) {
- // DEBUG ex.printStackTrace();
- } catch (IllegalStateException ex) {
- // DEBUG ex.printStackTrace();
- }
- }
- finally {
-
-
Thread.currentThread().setContextClassLoader(oldCl);
- }
- }
- }
-
-
- public void afterCompletion(int status)
- {
-
- // This is an independent point of entry. We need to make sure
the
- // thread is associated with the right context class loader
- ClassLoader oldCl =
Thread.currentThread().getContextClassLoader();
-
Thread.currentThread().setContextClassLoader(container.getClassLoader());
-
- try
- {
-
- //DEBUG Logger.debug("afterCompletion called for ctx
"+ctx.hashCode());
-
- // If rolled back -> invalidate instance
- // If removed -> send back to the pool
- if (status == Status.STATUS_ROLLEDBACK || ctx.getId()
== null) {
-
- try {
-
- // finish the transaction association
- ctx.setTransaction(null);
-
- // remove from the cache
-
container.getInstanceCache().remove(ctx.getCacheKey());
-
- // return to pool
- container.getInstancePool().free(ctx);
-
- } catch (Exception e) {
- // Ignore
- }
-
- } else {
-
- // We are afterCompletion so the invoked can
be set to false (db sync is done)
- ctx.setInvoked(false);
-
- switch (commitOption) {
- // Keep instance cached after tx commit
- case
ConfigurationMetaData.A_COMMIT_OPTION:
- // The state is still valid
(only point of access is us)
- ctx.setValid(true);
- break;
-
- // Keep instance active, but
invalidate state
- case
ConfigurationMetaData.B_COMMIT_OPTION:
- // Invalidate state (there
might be other points of entry)
- ctx.setValid(false);
- break;
-
- // Invalidate everything AND Passivate
instance
- case
ConfigurationMetaData.C_COMMIT_OPTION:
- try {
-
container.getInstanceCache().release(ctx);
- } catch (Exception e) {
- Logger.debug(e);
- }
- break;
- }
-
- // finish the transaction association
- ctx.setTransaction(null);
- }
- }
-
- finally {
-
- Thread.currentThread().setContextClassLoader(oldCl);
-
- // Notify all who are waiting for this tx to end, they
are waiting since the locking logic
- synchronized (ctx) {ctx.notifyAll();}
- }
- }
- }
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+
+ /**
+ * The current commit option.
+ */
+ protected int commitOption;
+
+ /**
+ * The container of this interceptor.
+ */
+ protected EntityContainer container;
+
+ /**
+ * Optional isModified method
+ */
+ protected Method isModified;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void setContainer(Container container)
+ {
+ this.container = (EntityContainer)container;
+ }
+
+ public void init()
+ throws Exception
+ {
+ commitOption =
container.getBeanMetaData().getContainerConfiguration().getCommitOption();
+ // Check for isModified method
+ try
+ {
+ isModified = container.getBeanClass().getMethod("isModified", new
Class[0]);
+ if (!isModified.getReturnType().equals(Boolean.TYPE))
+ isModified = null; // Has to have "boolean" as return type!
+ } catch (Exception e)
+ {
+ // Ignore
+ }
+ }
+
+ public Container getContainer()
+ {
+ return container;
+ }
+
+ /**
+ * Register a transaction synchronization callback with a context.
+ */
+ private void register(EntityEnterpriseContext ctx, Transaction tx)
+ {
+ // Create a new synchronization
+ InstanceSynchronization synch = new InstanceSynchronization(tx, ctx);
+
+ try {
+ // OSH: An extra check to avoid warning.
+ // Can go when we are sure that we no longer get
+ // the JTA violation warning.
+ if (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) {
+
+ ctx.setValid(false);
+
+ return;
+ }
+
+ // We want to be notified when the transaction commits
+ tx.registerSynchronization(synch);
+
+ } catch (RollbackException e) {
+
+ // The state in the instance is to be discarded, we force a reload of state
+ ctx.setValid(false);
+
+ } catch (Exception e) {
+
+ throw new EJBException(e);
+
+ }
+ }
+
+ private void deregister(EntityEnterpriseContext ctx)
+ {
+ // MF FIXME: I suspect this is redundant now
+ // (won't the pool clean it up?)
+
+ // Deassociate ctx with tx
+ // OSH: TxInterceptor seems to do this: ctx.setTransaction(null);
+ // OSH: Pool seems to do this: ctx.setInvoked(false);
+ }
+
+ // Interceptor implementation --------------------------------------
+
+ public Object invokeHome(MethodInvocation mi)
+ throws Exception
+ {
+ try {
+ return getNext().invokeHome(mi);
+ } finally {
+ // Anonymous was sent in, so if it has an id it was created
+ EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
+ if (ctx.getId() != null) {
+ Transaction tx = mi.getTransaction();
+
+ if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE)
+ register(ctx, tx); // Set tx
+
+ // Currently synched with underlying storage
+ ctx.setValid(true);
+ }
+ }
+ }
+
+ public Object invoke(MethodInvocation mi)
+ throws Exception
+ {
+ // We are going to work with the context a lot
+ EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
+
+ // The Tx coming as part of the Method Invocation
+ Transaction tx = mi.getTransaction();
+
+ //Logger.debug("CTX in: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
+ //Logger.debug("newTx: "+ tx);
+
+ // Is my state valid?
+ if (!ctx.isValid()) {
+
+ // If not tell the persistence manager to load the state
+ ((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
+
+ // Now the state is valid
+ ctx.setValid(true);
+ }
+
+ // So we can go on with the invocation
+ //DEBUG Logger.debug("Tx is "+ ((tx == null)? "null" :
tx.toString()));
+
+ // Invocation with a running Transaction
+
+ if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE) {
+
+ try {
+
+ //Invoke down the chain
+ return getNext().invoke(mi);
+
+ }
+
+ finally {
+
+ // Do we have a valid bean (not removed)
+ if (ctx.getId() != null) {
+
+ // If the context was not invoked previously...
+ if (!ctx.isInvoked()) {
+
+ // It is now and this will cause ejbStore to be called...
+ ctx.setInvoked(true);
+
+ // ... on a transaction callback that we register here.
+ register(ctx, tx);
+ }
+ }
+
+ // Entity was removed
+ else {
+
+ if (ctx.getTransaction() != null) {
+
+ //DEBUG Logger.debug("CTX out: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
+ //DEBUG Logger.debug("PresentTx:"+tx);
+
+ // If a ctx still has a transaction we would need to deresgister
the sync
+ // The simplest is to tell the pool to kill the instance if tx is
present
+
+ }
+ }
+ }
+ }
+
+ //
+ else { // No tx
+ try {
+ Object result = getNext().invoke(mi);
+
+ // Store after each invocation -- not on exception though, or removal
+ // And skip reads too ("get" methods)
+ // OSH FIXME: Isn't this startsWith("get") optimization a violation of
+ // the EJB specification? Think of SequenceBean.getNext().
+ if (ctx.getId() != null)
+ {
+ boolean dirty = true;
+ // Check isModified bean flag
+ if (isModified != null)
+ {
+ dirty = ((Boolean)isModified.invoke(ctx.getInstance(), new
Object[0])).booleanValue();
+ }
+
+ // Store entity
+ if (dirty)
+
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
+ }
+
+ return result;
+ } catch (Exception e) {
+ // Exception - force reload on next call
+ ctx.setValid(false);
+ throw e;
+ }
+ }
+ }
+
+
+ // Protected ----------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+
+ private class InstanceSynchronization
+ implements Synchronization
+ {
+ /**
+ * The transaction we follow.
+ */
+ private Transaction tx;
+
+ /**
+ * The context we manage.
+ */
+ private EntityEnterpriseContext ctx;
+
+ /**
+ * Create a new instance synchronization instance.
+ */
+ InstanceSynchronization(Transaction tx, EntityEnterpriseContext ctx)
+ {
+ this.tx = tx;
+ this.ctx = ctx;
+ }
+
+ // Synchronization implementation -----------------------------
+
+ public void beforeCompletion()
+ {
+ // DEBUG Logger.debug("beforeCompletion called for ctx "+ctx.hashCode());
+
+ if (ctx.getId() != null) {
+
+ // This is an independent point of entry. We need to make sure the
+ // thread is associated with the right context class loader
+ ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(container.getClassLoader());
+
+ try {
+
+ try {
+
+ // MF FIXME: should we throw an exception if lock is present (app
error)
+ // it would mean that someone is commiting when all the work is
not done
+
+ // Store instance if business method was invoked
+ if (ctx.isInvoked()) {
+
+ //DEBUG Logger.debug("EntitySynchronization sync calling store
on ctx "+ctx.hashCode());
+
+ // Check isModified bean flag
+ boolean dirty = true;
+ if (isModified != null)
+ {
+ try
+ {
+ dirty = ((Boolean)isModified.invoke(ctx.getInstance(), new
Object[0])).booleanValue();
+ } catch (Exception e)
+ {
+ // Ignore
+ e.printStackTrace();
+ }
+ }
+
+ if (dirty)
+ container.getPersistenceManager().storeEntity(ctx);
+ }
+ } catch (NoSuchEntityException e) {
+ // Object has been removed -- ignore
+ }
+ }
+ catch (RemoteException e) {
+ Logger.exception(e);
+
+ // Store failed -> rollback!
+ try {
+ tx.setRollbackOnly();
+ } catch (SystemException ex) {
+ // DEBUG ex.printStackTrace();
+ } catch (IllegalStateException ex) {
+ // DEBUG ex.printStackTrace();
+ }
+ }
+ finally {
+
+ Thread.currentThread().setContextClassLoader(oldCl);
+ }
+ }
+ }
+
+
+ public void afterCompletion(int status)
+ {
+
+ // This is an independent point of entry. We need to make sure the
+ // thread is associated with the right context class loader
+ ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(container.getClassLoader());
+
+ try
+ {
+
+ //DEBUG Logger.debug("afterCompletion called for ctx "+ctx.hashCode());
+
+ // If rolled back -> invalidate instance
+ // If removed -> send back to the pool
+ if (status == Status.STATUS_ROLLEDBACK || ctx.getId() == null) {
+
+ try {
+
+ // finish the transaction association
+ ctx.setTransaction(null);
+
+ // remove from the cache
+ container.getInstanceCache().remove(ctx.getCacheKey());
+
+ // return to pool
+ container.getInstancePool().free(ctx);
+
+ } catch (Exception e) {
+ // Ignore
+ }
+
+ } else {
+
+ // We are afterCompletion so the invoked can be set to false (db sync
is done)
+ ctx.setInvoked(false);
+
+ switch (commitOption) {
+ // Keep instance cached after tx commit
+ case ConfigurationMetaData.A_COMMIT_OPTION:
+ // The state is still valid (only point of access is us)
+ ctx.setValid(true);
+ break;
+
+ // Keep instance active, but invalidate state
+ case ConfigurationMetaData.B_COMMIT_OPTION:
+ // Invalidate state (there might be other points of entry)
+ ctx.setValid(false);
+ break;
+
+ // Invalidate everything AND Passivate instance
+ case ConfigurationMetaData.C_COMMIT_OPTION:
+ try {
+ container.getInstanceCache().release(ctx);
+ } catch (Exception e) {
+ Logger.debug(e);
+ }
+ break;
+ }
+
+ // finish the transaction association
+ ctx.setTransaction(null);
+ }
+ }
+
+ finally {
+
+ Thread.currentThread().setContextClassLoader(oldCl);
+
+ // Notify next waiting for this tx to end, they are waiting since
the locking logic
+ synchronized (ctx) {ctx.notify();}
+ }
+ }
+ }
}
1.23 +30 -16
jboss/src/main/org/jboss/ejb/plugins/EntityInstanceInterceptor.java
Index: EntityInstanceInterceptor.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/EntityInstanceInterceptor.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- EntityInstanceInterceptor.java 2000/10/20 03:11:43 1.22
+++ EntityInstanceInterceptor.java 2000/10/21 21:32:10 1.23
@@ -44,7 +44,7 @@
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a>
-* @version $Revision: 1.22 $
+* @version $Revision: 1.23 $
*/
public class EntityInstanceInterceptor
extends AbstractInterceptor
@@ -89,18 +89,22 @@
// Always unlock, no matter what
ctx.unlock();
- // Still free? Not free if create() was called successfully
- if (ctx.getId() == null)
- {
- container.getInstancePool().free(ctx);
- }
- else
- {
- // DEBUG Logger.debug("Entity was created; not returned
to pool");
- synchronized (ctx) {
+ synchronized (ctx) {
+
+ // Still free? Not free if create() was called successfully
+ if (ctx.getId() == null)
+ {
+ container.getInstancePool().free(ctx);
+
+ // the pool will notify all everyone
+ }
+ else
+ {
+ // DEBUG Logger.debug("Entity was created; not
returned to pool");
- //Let the waiters know
- ctx.notifyAll();
+ //Let one waiter know
+ ctx.notify();
+
}
}
}
@@ -146,7 +150,7 @@
Logger.debug("LOCKING-WAITING (TRANSACTION) for id
"+ctx.getId()+" ctx.hash "+ctx.hashCode()+" tx:"+((tx == null) ? "null" :
tx.toString()));
try {
- ctx.wait();
+ ctx.wait(5000);
} catch (InterruptedException ie) {}
// Try your luck again
@@ -173,7 +177,7 @@
Logger.debug("LOCKING-WAITING (CTX) for id
"+ctx.getId()+" ctx.hash "+ctx.hashCode());
try{
- ctx.wait();
+ ctx.wait(5000);
} catch (InterruptedException ie) {}
// Try your luck again
@@ -240,11 +244,21 @@
// It has been removed -> send to the pool
container.getInstancePool().free(ctx);
+
+ // The pool will notify everyone waiting on this
+
}
}
- // notify the thread waiting on ctx
- synchronized (ctx) { ctx.notifyAll();}
+ else {
+
+ // MF FIXME for speed reason I use notify
+ // however we would need to lock on the tx and ctx so we can
+ // notify the right population, slightly more complicated...
+
+ // notify the next thread waiting on ctx
+ synchronized (ctx) { ctx.notify();}
+ }
}
}
}
1.7 +15 -12 jboss/src/main/org/jboss/ejb/plugins/AbstractInstancePool.java
Index: AbstractInstancePool.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/AbstractInstancePool.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- AbstractInstancePool.java 2000/10/09 20:15:36 1.6
+++ AbstractInstancePool.java 2000/10/21 21:32:10 1.7
@@ -31,7 +31,7 @@
*
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
- * @version $Revision: 1.6 $
+ * @version $Revision: 1.7 $
*/
public abstract class AbstractInstancePool
implements InstancePool, XmlLoadable
@@ -128,8 +128,11 @@
// Pool it
//DEBUG Logger.debug("Free instance:"+ctx.getId()+"#"+ctx.getTransaction());
- ctx.clear();
+ ctx.clear();
+ // Free everyone waiting on that ctx
+ synchronized (ctx) {ctx.notifyAll();}
+
if (pool.size() < maxSize)
{
pool.push(ctx);
@@ -153,16 +156,16 @@
// Z implementation ----------------------------------------------
- // XmlLoadable implementation
- public void importXml(Element element) throws DeploymentException {
- String maximumSize =
MetaData.getElementContent(MetaData.getUniqueChild(element, "MaximumSize"));
- try {
- maxSize = Integer.parseInt(maximumSize);
- } catch (NumberFormatException e) {
- throw new DeploymentException("Invalid MaximumSize value for
instance pool configuration");
- }
- }
-
+ // XmlLoadable implementation
+ public void importXml(Element element) throws DeploymentException {
+ String maximumSize =
MetaData.getElementContent(MetaData.getUniqueChild(element, "MaximumSize"));
+ try {
+ maxSize = Integer.parseInt(maximumSize);
+ } catch (NumberFormatException e) {
+ throw new DeploymentException("Invalid MaximumSize value for instance pool
configuration");
+ }
+ }
+
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------