use of org.apache.openejb.core.NoSuchObjectException in project tomee by apache.
the class EntityInstanceManager method obtainInstance.
public EntityBean obtainInstance(final ThreadContext callContext) throws OpenEJBException {
// primary key is null if its a servicing a home methods (create, find, ejbHome)
final Object primaryKey = callContext.getPrimaryKey();
final TransactionPolicy txPolicy = callContext.getTransactionPolicy();
if (callContext.getPrimaryKey() != null && txPolicy != null && txPolicy.isTransactionActive()) {
final Key key = new Key(callContext.getBeanContext().getDeploymentID(), primaryKey);
SynchronizationWrapper wrapper = (SynchronizationWrapper) txPolicy.getResource(key);
if (wrapper != null) {
if (!wrapper.isAssociated()) {
/*
* If the bean identity was removed (via ejbRemove()) within the same transaction,
* then it's SynchronizationWrapper will be in the txReady pool but marked as disassociated.
* This allows us to prevent a condition where the caller removes the bean and then attempts to
* 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 {
// 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.
*/
final EntityBean bean = getPooledInstance(callContext);
wrapper = new SynchronizationWrapper(callContext.getBeanContext(), primaryKey, bean, false, key, txPolicy);
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();
}
txPolicy.registerSynchronization(wrapper);
loadingBean(bean, callContext);
final Operation orginalOperation = callContext.getCurrentOperation();
callContext.setCurrentOperation(Operation.LOAD);
try {
bean.ejbLoad();
} catch (final NoSuchEntityException e) {
wrapper.disassociate();
throw new InvalidateReferenceException(new NoSuchObjectException("Entity not found: " + primaryKey, e));
} catch (final Exception e) {
logger.error("Exception encountered during ejbLoad():", e);
// djencks not sure about this dissociate call
wrapper.disassociate();
throw new OpenEJBException(e);
} finally {
callContext.setCurrentOperation(orginalOperation);
}
txPolicy.putResource(key, wrapper);
return bean;
}
} else {
// returned to the pool -- depending on if the tx is a client initiated or container initiated.
return getPooledInstance(callContext);
}
}
Aggregations