* call a business method on that bean within the same transaction. After a bean is removed any
* subsequent invocations on that bean with the same transaction should throw a NoSuchEntityException.
* its likely that the application server would have already made the reference invalid, but this bit of
* code is an extra precaution.
*/
throw new InvalidateReferenceException(new NoSuchObjectException("Entity not found: " + primaryKey));
} else if (callContext.getCurrentOperation() == Operation.REMOVE) {
/*
* To avoid calling ejbStore( ) on a bean that after its removed, we can not delegate
* the wrapper is marked as disassociated from the transaction to avoid processing the
* beforeCompletion( ) method on the SynchronizationWrapper object.
*/
wrapper.disassociate();
}
if (wrapper.isAvailable() || wrapper.primaryKey.equals(primaryKey)) {
return wrapper.getEntityBean();
} else {
// If the bean is declared as reentrant then the instance may be accessed
// by more then one thread at a time. This is one of the reasons that reentrancy
// is bad. In this case beans must be programmed to be multi threaded. The other reason
// reentrancy is bad has to do with transaction isolation. Multiple instances writing to
// the same database records will inevitably cancel out previous writes within the same tx.
//
// In the future we may change this to return a new instance of the bean and to
// link it and its wrapper to the original wrapper, but for now we choose this strategy because
// its simpler to implement.
return wrapper.getEntityBean();
}
} else {
/*
* If no synchronized wrapper for the key exists
* Then the bean entity is being access by this transaction for the first time,
* so it needs to be enrolled in the transaction.
*/
EntityBean bean = getPooledInstance(callContext);
wrapper = new SyncronizationWrapper(callContext.getDeploymentInfo(), primaryKey, bean, false, key);
if (callContext.getCurrentOperation() == Operation.REMOVE) {
/*
* To avoid calling ejbStore( ) on a bean that after its removed, we can not delegate
* the wrapper is marked as disassociated from the transaction to avoid processing the
* beforeCompletion( ) method on the SynchronizationWrapper object.
*
* We have to still use a wrapper so we can detect when a business method is called after
* a ejbRemove() and act to prevent it from being processed.
*/
wrapper.disassociate();
}
try {
currentTx.registerSynchronization(wrapper);
} catch (javax.transaction.SystemException e) {
logger.error("Transaction Manager registerSynchronization() failed.", e);
throw new SystemException(e);
} catch (RollbackException e) {
throw new ApplicationException(new TransactionRolledbackException(e));
}
loadingBean(bean, callContext);
Operation orginalOperation = callContext.getCurrentOperation();
callContext.setCurrentOperation(Operation.LOAD);
try {
bean.ejbLoad();
} catch (NoSuchEntityException e) {
throw new InvalidateReferenceException(new NoSuchObjectException("Entity not found: " + primaryKey).initCause(e));
} catch (Exception e) {
logger.error("Exception encountered during ejbLoad():", e);
throw new OpenEJBException(e);
} finally {